guowenxue
2020-01-09 f2ad9b27bbaec2adafdbf499eee750830a762d9d
Add fl2440 linux-bsp folders
1 files modified
148 files added
45709 ■■■■■ changed files
README.md 2 ●●● patch | view | raw | blame | history
linux-bsp/asm-study/asm/asm_c_buzzer/beep.c 41 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/asm/asm_c_buzzer/beep.lds 29 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/asm/asm_c_buzzer/makefile 51 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/asm/asm_c_buzzer/start.S 39 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/asm/asm_c_key_led/buzzer_led.c 97 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/asm/asm_c_key_led/key.lds 29 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/asm/asm_c_key_led/makefile 51 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/asm/asm_c_key_led/start.S 91 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/asm/asm_c_led/led.c 77 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/asm/asm_c_led/led.lds 29 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/asm/asm_c_led/makefile 51 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/asm/asm_c_led/start.S 75 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/asm/asm_led/led.S 93 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/asm/asm_led/makefile 51 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/asm/c_led/led.c 58 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/asm/c_led/led.lds 29 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/asm/c_led/makefile 51 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/bignum.c 1842 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/bootstrap.c 122 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/bootstrap.lds 32 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/common.c 413 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/crc32.c 218 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/asm/errno.h 138 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/asm/hardware.h 43 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/asm/io.h 330 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/asm/posix_types.h 80 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/asm/sizes.h 52 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/asm/types.h 53 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/bignum.h 380 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/bn_asm.h 549 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/common.h 52 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/config.h 36 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/linux/bitops.h 75 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/linux/config.h 6 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/linux/ctype.h 54 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/linux/posix_types.h 49 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/linux/stddef.h 18 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/linux/string.h 89 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/linux/time.h 149 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/linux/types.h 131 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/nand.h 271 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/rsa.h 208 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/s3c2440.h 674 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/include/s3c24x0.h 1125 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/interrupt.c 39 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/k9f2g08.c 638 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/led_beep.c 56 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/makefile 118 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/mem_init.S 170 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/nand.h 271 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/rsa.c 602 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/serial.c 74 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/start.S 348 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/myboot/xmodem.c 121 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/bootstrap.c 202 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/bootstrap.lds 32 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/bsp/eabi_compat.c 29 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/bsp/k9f2g08_api.c 276 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/bsp/k9f2g08_api.h 14 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/bsp/k9f2g08_s3c.h 177 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/bsp/makefile 102 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/bsp/s3c2440.h 646 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/bsp/s3c_board.c 213 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/bsp/s3c_board.h 34 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/common/dlmalloc.c 3320 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/common/makefile 97 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/common/malloc.h 947 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/common/printf.c 374 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/common/stdio.h 32 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/common/string.c 603 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/common/string.h 86 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/common/types.h 99 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/makefile 104 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/start.S 60 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/makefile 97 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_allocator.c 357 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_allocator.h 30 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_attribs.c 124 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_attribs.h 28 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_bitmap.c 97 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_bitmap.h 33 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_checkptrw.c 473 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_checkptrw.h 33 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_ecc.c 281 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_ecc.h 44 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_error.c 58 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_flashif.h 35 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_flashif2.h 35 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_getblockinfo.h 35 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_guts.c 5053 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_guts.h 977 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_hweight.c 53 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_hweight.h 24 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_k9f2g08.c 144 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_k9f2g08.h 13 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_list.h 126 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_nameval.c 208 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_nameval.h 28 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_nand.c 120 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_nand.h 38 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_osglue.c 170 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_osglue.h 44 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_packedtags2.c 197 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_packedtags2.h 47 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_qsort.c 163 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_summary.c 313 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_summary.h 37 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_tagscompat.c 407 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_tagscompat.h 36 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_trace.h 57 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_verify.c 529 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_verify.h 43 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_yaffs1.c 422 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_yaffs1.h 22 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_yaffs2.c 1532 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_yaffs2.h 39 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffscfg.h 55 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffscfg2k.c 121 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffsfs.c 3461 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yaffsfs.h 233 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/ydirectenv.h 99 ●●●●● patch | view | raw | blame | history
linux-bsp/asm-study/yaffs2/yaffs2/yportenv.h 318 ●●●●● patch | view | raw | blame | history
linux-bsp/bootstrap/bootstrap.S 156 ●●●●● patch | view | raw | blame | history
linux-bsp/bootstrap/bootstrap.h 148 ●●●●● patch | view | raw | blame | history
linux-bsp/bootstrap/build.sh 52 ●●●●● patch | view | raw | blame | history
linux-bsp/bootstrap/makefile 55 ●●●●● patch | view | raw | blame | history
linux-bsp/build.sh 293 ●●●●● patch | view | raw | blame | history
linux-bsp/driver/Makefile 46 ●●●●● patch | view | raw | blame | history
linux-bsp/driver/kernel_hello.c 35 ●●●●● patch | view | raw | blame | history
linux-bsp/driver/platdev_led.c 111 ●●●●● patch | view | raw | blame | history
linux-bsp/driver/platdev_led.h 67 ●●●●● patch | view | raw | blame | history
linux-bsp/driver/platdrv_key.c 339 ●●●●● patch | view | raw | blame | history
linux-bsp/driver/platdrv_led.c 297 ●●●●● patch | view | raw | blame | history
linux-bsp/driver/s3c_led.c 281 ●●●●● patch | view | raw | blame | history
linux-bsp/driver/test/makefile 46 ●●●●● patch | view | raw | blame | history
linux-bsp/driver/test/test_plat_key.c 279 ●●●●● patch | view | raw | blame | history
linux-bsp/driver/test/test_plat_led.c 72 ●●●●● patch | view | raw | blame | history
linux-bsp/driver/test/test_s3c_led.c 81 ●●●●● patch | view | raw | blame | history
linux-bsp/driver/x86/Makefile 29 ●●●●● patch | view | raw | blame | history
linux-bsp/driver/x86/kernel_hello.c 1 ●●●● patch | view | raw | blame | history
linux-bsp/patches/gen_patch.sh 71 ●●●●● patch | view | raw | blame | history
linux-bsp/patches/linux-3.0-fl2440.patch 4153 ●●●●● patch | view | raw | blame | history
linux-bsp/patches/u-boot-2010.09-fl2440.patch 2075 ●●●●● patch | view | raw | blame | history
linux-bsp/patches/u-boot-serial-patch/u-boot-2010.09-1-basic.patch 1765 ●●●●● patch | view | raw | blame | history
linux-bsp/patches/u-boot-serial-patch/u-boot-2010.09-2-dm9000.patch 70 ●●●●● patch | view | raw | blame | history
linux-bsp/patches/u-boot-serial-patch/u-boot-2010.09-3-nand.patch 190 ●●●●● patch | view | raw | blame | history
linux-bsp/patches/u-boot-serial-patch/u-boot-2010.09-4-linux.patch 91 ●●●●● patch | view | raw | blame | history
linux-bsp/tarballs/rootfs.tar.bz2 patch | view | raw | blame | history
README.md
@@ -1,4 +1,4 @@
## fl2440
FL2440开发板源码
FL2440 ARM Linux Board BSP and application
linux-bsp/asm-study/asm/asm_c_buzzer/beep.c
New file
@@ -0,0 +1,41 @@
/***********************************************************************
 *        File:  beep.c
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  This C code used to turn buzzer on/off on FL2440 board
 *   ChangeLog:  1, Release initial version on "Mon Mar 21 21:09:52 CST 2011"
 *
 ***********************************************************************/
#define GPBCON   (*(unsigned long volatile *)0x56000010)
#define GPBDAT   (*(unsigned long volatile *)0x56000014)
#define GPBUP    (*(unsigned long volatile *)0x56000018)
#define BEEP         0    /*Buzzer us GPB0 */
#define LED0         5
#define DELAY_TIME   40000000
static inline void delay (unsigned long loops)
{
    __asm__ volatile ("1:\n"
            "subs %0, %1, #1\n"
            "bne 1b":"=r" (loops):"0" (loops));
}
int main(void)
{
    GPBCON = (GPBCON|0x3)&0x1; /* Set GPB0 as GPIO output mode(0x01) */
    GPBUP &= ~1;               /* Enable pullup resister */
    GPBDAT |= 0x560;
    while(1)
    {
        GPBDAT &= ~(1<<BEEP);  /* Set Beep GPIO as low level */
        delay(DELAY_TIME);
        GPBDAT |= 1<<BEEP;     /* Set Beep GPIO as high level */
        delay(DELAY_TIME);
    }
}
linux-bsp/asm-study/asm/asm_c_buzzer/beep.lds
New file
@@ -0,0 +1,29 @@
/***********************************************************************
 *        File:  beep.lds
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  Cross tool link text, refer to u-boot.lds
 *   ChangeLog:  1, Release initial version on "Mon Mar 21 21:09:52 CST 2011"
 *
 ***********************************************************************/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS{
    . = 0x33000000;
    .text : {
        *(.text)
        *(.rodata)
    }
    .data ALIGN(4): {
        *(.data)
    }
    .bss ALIGN(4): {
        *(.bss)
    }
}
linux-bsp/asm-study/asm/asm_c_buzzer/makefile
New file
@@ -0,0 +1,51 @@
# ***********************************************************************
# *        File:  makefile
# *     Version:  1.0.0
# *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
# * Description:  Makefile used to cross compile the ASM and C source code
# *   ChangeLog:  1, Release initial version on "Mon Mar 21 21:09:52 CST 2011"
# *
# ***********************************************************************
BINAME = beep
TEXTBASE = 0x33000000
CROSS = /opt/xtools/arm920t/bin/arm-linux-
CC      = $(CROSS)gcc
LD      = $(CROSS)ld
AR      = $(CROSS)ar
OBJCOPY = $(CROSS)objcopy
OBJDUMP = $(CROSS)objdump
STRIP   = $(CROSS)strip
READELF = $(CROSS)readelf
CFLAGS  = -g -O2 -Wall -nostdinc -nostdlib -fno-builtin
AFLAGS  = $(CFLAGS) -D__ASSEMBLY__
LDSCRIPT = ${BINAME}.lds
LDFLAGS  = -nostartfiles -T $(LDSCRIPT) -Ttext $(TEXTBASE)
SRC_C   = $(wildcard *.c)
SRC_S   = $(wildcard *.S)
OBJ_C   = $(patsubst %.c,%.o,$(SRC_C))
OBJ_S   = $(patsubst %.S,%.o,$(SRC_S))
OBJ_ALL = $(OBJ_C) $(OBJ_S)
.PHONY : all
all: ${OBJ_ALL}
    ${LD} $(LDFLAGS) -o ${BINAME}.elf ${OBJ_ALL}
    ${OBJCOPY} -O binary -S ${BINAME}.elf ${BINAME}.bin
    rm -f *.elf *.o
%.o: %.S
            $(CC) $(AFLAGS) -c -o $@ $<
%.o: %.c
            $(CC) $(CFLAGS) -c -o $@ $<
install:
    cp ${BINAME}.bin ~/winxp -f --reply=yes
clean:
    rm -f *.elf *.o
    rm -f ${BINAME}.bin
linux-bsp/asm-study/asm/asm_c_buzzer/start.S
New file
@@ -0,0 +1,39 @@
/***********************************************************************
 *        File:  start.S
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  This ASM used to disable watch dog and interrupt, then call C code to
 *               turn the buzzer on/off on FL2440 board.
 *   ChangeLog:  1, Release initial version on "Mon Mar 21 21:09:52 CST 2011"
 *
 ***********************************************************************/
#define pWTCON    0x53000000  /* Watch dog register address */
#define INTMSK    0x4A000008  /* Interupt-Controller base addresses */
#define INTSUBMSK 0x4A00001C
    .text
    .align 2
    .global _start
_start:
    /* Disable watch dog */
    ldr r0, =pWTCON  /*Save pwTCON address in r0*/
    mov r1, #0x0     /*Set r1=0x0*/
    str r1, [r0]     /*Move the data in r1 to the address specify by r0*/
    /* mask all IRQs by setting all bits in the INTMR - default */
    mov r1, #0xffffffff
    ldr r0, =INTMSK
    str r1, [r0]
    ldr r0, =INTSUBMSK
    ldr r1, =0x7fff    /*There are 15 bits used in INTSUBMSK on S3C2440*/
    str r1, [r0]
    bl main
halt_loop:
    b halt_loop
linux-bsp/asm-study/asm/asm_c_key_led/buzzer_led.c
New file
@@ -0,0 +1,97 @@
/***********************************************************************
 *        File:  buzzer_led.c
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  This C code used to turn buzzer on/off on FL2440 board
 *   ChangeLog:  1, Release initial version on "Tue Mar 22 21:58:24 CST 2011"
 *
 ***********************************************************************/
#define GPBCON   (*(unsigned long volatile *)0x56000010)
#define GPBDAT   (*(unsigned long volatile *)0x56000014)
#define GPBUP    (*(unsigned long volatile *)0x56000018)
#define BEEP     0    /* Buzzer use GPB0 */
#define LED0     5    /* LED0 use GPB5*/
#define LED1     6    /* LED1 use GPB6*/
#define LED2     8    /* LED2 use GPB8*/
#define LED3     10   /* LED3 use GPB10*/
#define DELAY_TIME   40000000
unsigned int led_gpio[4] = {5,6,8,10};
static inline void delay (unsigned long loops)
{
    __asm__ volatile ("1:\n"
            "subs %0, %1, #1\n"
            "bne 1b":"=r" (loops):"0" (loops));
}
void init_led_buzzer(void)
{
    GPBCON = (GPBCON|0x333C03)&0x111401; /* Set GPB0,GPB5,GPB8,GPB10 as GPIO input mode */
    GPBDAT |= 0x560;   /* Set GPB0,GPB5,GPB6,GPB8,GPB10 as high level */
}
void turn_led_on(int led)
{
    if(led > 3)
        return;
    /* Set GPIO port as low level */
    GPBDAT = (GPBDAT & ( ~(1<<led_gpio[led])) );
}
/* Turn all LED off */
void turn_all_led_off(void)
{
    GPBDAT |= 0x560; /* Set GPIO port as high level */
}
void turn_beep_on(void)
{
    GPBDAT |= 1<<BEEP;     /* Set Beep GPIO as high level, turn beep on */
}
void turn_beep_off(void)
{
    GPBDAT &= ~(1<<BEEP);  /* Set Beep GPIO as low level, turn beep off */
}
void turn_buzzer(int times)
{
    int      i;
    for(i=0; i<times; i++)
    {
        turn_beep_on();
        delay(DELAY_TIME);
        turn_beep_off();
        delay(DELAY_TIME);
    }
}
void turn_led_buzzer_off(void)
{
    turn_all_led_off();
    turn_beep_off();
    return;
}
/* Input value $key is passed by start.S
 *
 * Key2 pressed -> key=0, turn LED0 on, beep for 1 time
 * Key3 pressed -> key=1, turn LED1 on, beep for 2 time
 * Key4 pressed -> key=2, turn LED2 on, beep for 3 time
 * Key5 pressed -> key=3, turn LED3 on, beep for 4 time
 */
void turn_led_buzzer_on(int key)
{
    turn_led_on(key);    /* Set correspond LED on */
    turn_buzzer(key+1);  /* Let buzzer beep for $key times */
}
linux-bsp/asm-study/asm/asm_c_key_led/key.lds
New file
@@ -0,0 +1,29 @@
/***********************************************************************
 *        File:  key.lds
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  Cross tool link text, refer to u-boot.lds
 *   ChangeLog:  1, Release initial version on "Tue Mar 22 21:58:24 CST 2011"
 *
 ***********************************************************************/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS{
    . = 0x33000000;
    .text : {
        *(.text)
        *(.rodata)
    }
    .data ALIGN(4): {
        *(.data)
    }
    .bss ALIGN(4): {
        *(.bss)
    }
}
linux-bsp/asm-study/asm/asm_c_key_led/makefile
New file
@@ -0,0 +1,51 @@
# ***********************************************************************
# *        File:  makefile
# *     Version:  1.0.0
# *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
# * Description:  Makefile used to cross compile the ASM and C source code
# *   ChangeLog:  1, Release initial version on "Mon Mar 21 21:09:52 CST 2011"
# *
# ***********************************************************************
BINAME = key
TEXTBASE = 0x33000000
CROSS = /opt/xtools/arm920t/bin/arm-linux-
CC      = $(CROSS)gcc
LD      = $(CROSS)ld
AR      = $(CROSS)ar
OBJCOPY = $(CROSS)objcopy
OBJDUMP = $(CROSS)objdump
STRIP   = $(CROSS)strip
READELF = $(CROSS)readelf
CFLAGS  = -g -O2 -Wall -nostdinc -nostdlib -fno-builtin
AFLAGS  = $(CFLAGS) -D__ASSEMBLY__
LDSCRIPT = ${BINAME}.lds
LDFLAGS  = -nostartfiles -T $(LDSCRIPT) -Ttext $(TEXTBASE)
SRC_C   = $(wildcard *.c)
SRC_S   = $(wildcard *.S)
OBJ_C   = $(patsubst %.c,%.o,$(SRC_C))
OBJ_S   = $(patsubst %.S,%.o,$(SRC_S))
OBJ_ALL = $(OBJ_C) $(OBJ_S)
.PHONY : all
all: ${OBJ_ALL}
    ${LD} $(LDFLAGS) -o ${BINAME}.elf ${OBJ_ALL}
    ${OBJCOPY} -O binary -S ${BINAME}.elf ${BINAME}.bin
    rm -f *.elf *.o
%.o: %.S
            $(CC) $(AFLAGS) -c -o $@ $<
%.o: %.c
            $(CC) $(CFLAGS) -c -o $@ $<
install:
    cp ${BINAME}.bin ~/winxp -f --reply=yes
clean:
    rm -f *.elf *.o
    rm -f ${BINAME}.bin
linux-bsp/asm-study/asm/asm_c_key_led/start.S
New file
@@ -0,0 +1,91 @@
/***********************************************************************
 *        File:  start.S
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  This ASM used to detect the four keys status, if it's pressed down
 *               then call the C function to turn the buzzer beep and LED on
 *   ChangeLog:  1, Release initial version on "Tue Mar 22 21:58:24 CST 2011"
 *
 ***********************************************************************/
#define pWTCON    0x53000000  /* Watch dog register address */
#define INTMSK    0x4A000008  /* Interupt-Controller base addresses */
#define INTSUBMSK 0x4A00001C
#define GPFCON    0x56000050
#define GPFDAT    0x56000054
#define GPFUP     0x56000058
#define KEY2      0  /*KEY S2 use GPF0/EINT0 port*/
#define KEY3      2  /*KEY S3 use GPF2/EINT2 port*/
#define KEY4      3  /*KEY S4 use GPF3/EINT3 port*/
#define KEY5      4  /*KEY S5 use GPF4/EINT4 port*/
    .text
    .align 2
    .global _start
_start:
    /* Disable watch dog */
    ldr r0, =pWTCON  /*Save pwTCON address in r0*/
    mov r1, #0x0     /*Set r1=0x0*/
    str r1, [r0]     /*Move the data in r1 to the address specify by r0*/
    /* mask all IRQs by setting all bits in the INTMR - default */
    mov r1, #0xffffffff
    ldr r0, =INTMSK
    str r1, [r0]
    ldr r0, =INTSUBMSK
    ldr r1, =0x7fff    /*There are 15 bits used in INTSUBMSK on S3C2440*/
    str r1, [r0]
    /*Set Beep GPIO port as GPIO input mode*/
    ldr r0, =GPFCON
    ldr r1, [r0]
    bic r1, r1, #0xf3    /* Set GPF0, GPF2, GPF3, as GPIO input mode(00)*/
    bic r1, r1, #0x0300  /* Set GPF4 as GPIO input mode(00)*/
    str r1, [r0]
    bl init_led_buzzer  /*Call C function to init buzzer and LED GPIO port*/
loop_detect:
    bl turn_led_buzzer_off
    ldr r1, =GPFDAT   /*Read the four key GPIO data port*/
    ldr r2, [r1]
    /*Check Key2 pressed down or not*/
    mov r0, #0  /*Turn LED0 on*/
    tst r2, #0x1
    bleq led_beep_on
    /*Check Key3 pressed down or not*/
    mov r0, #1  /*Turn LED1 on*/
    tst r2, #0x4
    bleq led_beep_on
    /*Check Key4 pressed down or not*/
    mov r0, #2  /*Turn LED2 on*/
    tst r2, #0x8
    bleq led_beep_on
    /*Check Key5 pressed down or not*/
    mov r0, #3  /*Turn LED3 on*/
    tst r2, #0x10
    bleq led_beep_on
    /*No key pressed, detect again*/
    b loop_detect
led_beep_on:
    bl turn_led_buzzer_on  /*Turn buzzer beep*/
    @mov pc, lr    /*Why mov lr, pc can not work?*/
    b loop_detect
    /*Won't come here*/
halt_loop:
    b halt_loop
linux-bsp/asm-study/asm/asm_c_led/led.c
New file
@@ -0,0 +1,77 @@
/***********************************************************************
 *        File:  led.c
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  This C code used to turn LED0~LED4 on on FL2440 board
 *   ChangeLog:  1, Release initial version on "Mon Mar 21 21:09:52 CST 2011"
 *
 ***********************************************************************/
#define GPBCON   (*(unsigned long volatile *)0x56000010)
#define GPBDAT   (*(unsigned long volatile *)0x56000014)
#define GPBUP    (*(unsigned long volatile *)0x56000018)
#define LED0     5    /*LED0 use GPB5*/
#define LED1     6    /*LED1 use GPB6*/
#define LED2     8    /*LED2 use GPB8*/
#define LED3     10   /*LED3 use GPB10*/
#define DELAY_TIME   1000000
static inline void delay (unsigned long loops)
{
    __asm__ volatile ("1:\n"
        "subs %0, %1, #1\n"
        "bne 1b":"=r" (loops):"0" (loops));
}
void led_init(void)
{
    /*  Set GPB5,GPB6,GPB8,GPB10 as GPIO mode(0x01) */
    GPBCON = (GPBCON|0x333C00)&0x111400;
    GPBUP = (GPBUP | 0x560);
    /* Set GPB5,GPB6,GPB8,GPB10 as high level, to turn LED0,LED1,LED2,LED3 off */
    GPBDAT = (GPBDAT | 0x560);
}
int main(void)
{
    led_init();
    while(1)
    {
        /* Set GPB5,GPB6,GPB8,GPB10 as high level, to turn LED0,LED1,LED2,LED3 off */
        GPBDAT = (GPBDAT | 0x560);
        delay(DELAY_TIME);
        /* Turn LED0 on */
        GPBDAT = (GPBDAT & (~(1<<LED0)) );
        delay(DELAY_TIME);
        /* Turn LED1 on */
        GPBDAT = (GPBDAT & (~(1<<LED1)) );
        delay(DELAY_TIME);
        /* Turn LED2 on */
        GPBDAT = (GPBDAT & (~(1<<LED2)) );
        delay(DELAY_TIME);
        /* Turn LED3 on */
        GPBDAT = (GPBDAT & (~(1<<LED3)) );
        delay(DELAY_TIME);
    }
}
void turn_led_on(int led)
{
     GPBDAT = (GPBDAT & (~(1<<led)) );
     delay(DELAY_TIME);
}
void turn_led_off(int led)
{
     /* Turn LED0 on */
     GPBDAT = (GPBDAT | (1<<led) );
     delay(DELAY_TIME);
}
linux-bsp/asm-study/asm/asm_c_led/led.lds
New file
@@ -0,0 +1,29 @@
/***********************************************************************
 *        File:  led.lds
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  Cross tool link text, refer to u-boot.lds
 *   ChangeLog:  1, Release initial version on "Mon Mar 21 21:09:52 CST 2011"
 *
 ***********************************************************************/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS{
    . = 0x33000000;
    .text : {
        *(.text)
        *(.rodata)
    }
    .data ALIGN(4): {
        *(.data)
    }
    .bss ALIGN(4): {
        *(.bss)
    }
}
linux-bsp/asm-study/asm/asm_c_led/makefile
New file
@@ -0,0 +1,51 @@
# ***********************************************************************
# *        File:  makefile
# *     Version:  1.0.0
# *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
# * Description:  Makefile used to cross compile the ASM and C source code
# *   ChangeLog:  1, Release initial version on "Mon Mar 21 21:09:52 CST 2011"
# *
# ***********************************************************************
BINAME = led
TEXTBASE = 0x33000000
CROSS = /opt/xtools/arm920t/bin/arm-linux-
CC      = $(CROSS)gcc
LD      = $(CROSS)ld
AR      = $(CROSS)ar
OBJCOPY = $(CROSS)objcopy
OBJDUMP = $(CROSS)objdump
STRIP   = $(CROSS)strip
READELF = $(CROSS)readelf
CFLAGS  = -g -O2 -Wall -nostdinc -nostdlib -fno-builtin
AFLAGS  = $(CFLAGS) -D__ASSEMBLY__
LDSCRIPT = ${BINAME}.lds
LDFLAGS  = -nostartfiles -T $(LDSCRIPT) -Ttext $(TEXTBASE)
SRC_C   = $(wildcard *.c)
SRC_S   = $(wildcard *.S)
OBJ_C   = $(patsubst %.c,%.o,$(SRC_C))
OBJ_S   = $(patsubst %.S,%.o,$(SRC_S))
OBJ_ALL = $(OBJ_C) $(OBJ_S)
.PHONY : all
all: ${OBJ_ALL}
    ${LD} $(LDFLAGS) -o ${BINAME}.elf ${OBJ_ALL}
    ${OBJCOPY} -O binary -S ${BINAME}.elf ${BINAME}.bin
    rm -f *.elf *.o
%.o: %.S
            $(CC) $(AFLAGS) -c -o $@ $<
%.o: %.c
            $(CC) $(CFLAGS) -c -o $@ $<
install:
    cp ${BINAME}.bin ~/winxp -f --reply=yes
clean:
    rm -f *.elf *.o
    rm -f ${BINAME}.bin
linux-bsp/asm-study/asm/asm_c_led/start.S
New file
@@ -0,0 +1,75 @@
/***********************************************************************
 *        File:  start.S
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  This ASM used to disable watch dog and interrupt, then call C code to
 *               turn the four LEDs on/off on FL2440 board.
 *   ChangeLog:  1, Release initial version on "Mon Mar 21 21:09:52 CST 2011"
 *
 ***********************************************************************/
#define pWTCON    0x53000000  /* Watch dog register address */
#define INTMSK    0x4A000008  /* Interupt-Controller base addresses */
#define INTSUBMSK 0x4A00001C
#define LED0     5    /*LED0 use GPB5*/
#define LED1     6    /*LED1 use GPB6*/
#define LED2     8    /*LED2 use GPB8*/
#define LED3     10   /*LED3 use GPB10*/
    .text
    .align 2
    .global _start
_start:
    /* Disable watch dog */
    ldr r0, =pWTCON  /*Save pwTCON address in r0*/
    mov r1, #0x0     /*Set r1=0x0*/
    str r1, [r0]     /*Move the data in r1 to the address specify by r0*/
    /* mask all IRQs by setting all bits in the INTMR - default */
    mov r1, #0xffffffff
    ldr r0, =INTMSK
    str r1, [r0]
    ldr r0, =INTSUBMSK
    ldr r1, =0x7fff    /*There are 15 bits used in INTSUBMSK on S3C2440*/
    str r1, [r0]
    bl  led_init
loop:
    mov r0,#LED0
    bl turn_led_on
    mov r0,#LED1
    bl turn_led_on
    mov r0,#LED2
    bl turn_led_on
    mov r0,#LED3
    bl turn_led_on
    mov r0,#LED0
    bl turn_led_off
    mov r0,#LED1
    bl turn_led_off
    mov r0,#LED2
    bl turn_led_off
    mov r0,#LED3
    bl turn_led_off
    b loop
    @bl main
halt_loop:
    b halt_loop
linux-bsp/asm-study/asm/asm_led/led.S
New file
@@ -0,0 +1,93 @@
/***********************************************************************
 *        File:  led.S
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  This ASM code used to turn LED0~LED4 on/off on FL2440 board
 *   ChangeLog:  1, Release initial version on "Sun Mar 20 18:41:04 CST 2011"
 *
 ***********************************************************************/
#define GPBCON   0x56000010
#define GPBDAT   0x56000014
#define GPBUP    0x56000018
#define OUTPUT   0x01   /*Set GPIO port as output mode*/
#define INPUT    0x00   /*Set GPIO port as input mode*/
#define BEEP     0      /*On FL2440 board, LED0 use GPB0*/
#define LED0     5      /*On FL2440 board, LED0 use GPB5*/
#define LED1     6      /*On FL2440 board, LED0 use GPB6*/
#define LED2     8      /*On FL2440 board, LED0 use GPB8*/
#define LED3     10     /*On FL2440 board, LED0 use GPB10*/
#define DELAY    0X1000000
    .text
    .align 2
    .global _start
_start:
    /*Set GPIO5, GPIO6, GPIO8, GPIO10 as GPIO OUTPUT mode*/
    ldr     r0, =GPBCON
    ldr     r1, [r0]
    bic     r1, r1, #0x3c00      /*Set GPBCON for GPIO5,GPIO6 as 0x00 */
    orr     r1, r1, #0x1400      /*Set GPBCON for GPIO5,GPIO6 as GPIOOUT, 0x01*/
    bic     r1, r1, #0x00330000  /*Set GPBCON for GPIO8,GPIO10 as 0x00*/
    orr     r1, r1, #0x00110000  /*Set GPBCON for GPIO8,GPIO10 as GPIOOUT, 0x01*/
    str     r1, [r0]
    /*Set internal pullup resister*/
    ldr     r0, =GPBUP
    ldr     r1, [r0]
    orr     r1, r1, #0x0560     /*Set bit 5,6,8,10, disable pullup resister*/
    @bic     r1, r1, #0x0560      /*Clear bit 5,6,8,10, enable pullup resister*/
    str     r1, [r0]
loopled:
    /*Turn off LED5, LED6, LED8, LED10*/
    ldr     r2, =GPBDAT
    ldr     r3, [r2]
    orr     r3, r3, #0x0560     /*Set bit 5,6,8,10 as high level*/
    str     r3, [r2]
    ldr     r0, =DELAY          /*Sleep for a while*/
    bl      delay
    /*Turn on LED0*/
    ldr     r3, [r2]
    bic     r3, r3, #(1<<LED0)  /*Clear bit 5, set GPB5 as low level*/
    str     r3, [r2]
    ldr     r0, =DELAY          /*Sleep for a while*/
    bl      delay
    /*Turn on LED1*/
    ldr     r3, [r2]
    bic     r3, r3, #(1<<LED1)  /*Clear bit 6, set GPB6 as low level*/
    str     r3, [r2]
    ldr     r0, =DELAY          /*Sleep for a while*/
    bl      delay
    /*Turn on LED2*/
    ldr     r3, [r2]
    bic     r3, r3, #(1<<LED2)  /*Clear bit 8, set GPB8 as low level*/
    str     r3, [r2]
    ldr     r0, =DELAY          /*Sleep for a while*/
    bl      delay
    /*Turn on LED3*/
    ldr     r3, [r2]
    bic     r3, r3, #(1<<LED3)  /*Clear bit 10, set GPB10 as low level*/
    str     r3, [r2]
    ldr     r0, =DELAY          /*Sleep for a while*/
    bl      delay
    b       loopled             /*Loop running LED*/
delay:
    sub     r0, r0, #1
    cmp     r0, #0x0
    bne     delay
    mov     pc, lr
linux-bsp/asm-study/asm/asm_led/makefile
New file
@@ -0,0 +1,51 @@
# ***********************************************************************
# *        File:  makefile
# *     Version:  1.0.0
# *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
# * Description:  Makefile used to cross compile the ASM and C source code
# *   ChangeLog:  1, Release initial version on "Mon Mar 21 21:09:52 CST 2011"
# *
# ***********************************************************************
BINAME = led
TEXTBASE = 0x33000000
#TEXTBASE =0
CROSS = /opt/xtools/arm920t/bin/arm-linux-
CC      = $(CROSS)gcc
LD      = $(CROSS)ld
AR      = $(CROSS)ar
OBJCOPY = $(CROSS)objcopy
OBJDUMP = $(CROSS)objdump
STRIP   = $(CROSS)strip
READELF = $(CROSS)readelf
CFLAGS  = -g -O2 -Wall -nostdinc -nostdlib -fno-builtin
AFLAGS  = $(CFLAGS) -D__ASSEMBLY__
LDFLAGS  = -Ttext $(TEXTBASE)
SRC_C   = $(wildcard *.c)
SRC_S   = $(wildcard *.S)
OBJ_C   = $(patsubst %.c,%.o,$(SRC_C))
OBJ_S   = $(patsubst %.S,%.o,$(SRC_S))
OBJ_ALL = $(OBJ_C) $(OBJ_S)
.PHONY : all
all: ${OBJ_ALL}
    ${LD} $(LDFLAGS) -o ${BINAME}.elf ${OBJ_ALL}
    ${OBJCOPY} -O binary -S ${BINAME}.elf ${BINAME}.bin
    rm -f *.elf *.o
%.o: %.S
            $(CC) $(AFLAGS) -c -o $@ $<
%.o: %.c
            $(CC) $(CFLAGS) -c -o $@ $<
install:
    cp ${BINAME}.bin ~/winxp -f --reply=yes
clean:
    rm -f *.elf *.o
    rm -f ${BINAME}.bin
linux-bsp/asm-study/asm/c_led/led.c
New file
@@ -0,0 +1,58 @@
/***********************************************************************
 *        File:  led.c
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  This C code used to turn LED0~LED4 on on FL2440 board
 *   ChangeLog:  1, Release initial version on "Mon Mar 21 21:09:52 CST 2011"
 *
 ***********************************************************************/
#define GPBCON   (*(unsigned long volatile *)0x56000010)
#define GPBDAT   (*(unsigned long volatile *)0x56000014)
#define GPBUP    (*(unsigned long volatile *)0x56000018)
#define LED0     5    /*LED0 use GPB5*/
#define LED1     6    /*LED1 use GPB6*/
#define LED2     8    /*LED2 use GPB8*/
#define LED3     10   /*LED3 use GPB10*/
#define DELAY_TIME   20000000
static inline void delay (unsigned long loops)
{
    __asm__ volatile ("1:\n"
        "subs %0, %1, #1\n"
        "bne 1b":"=r" (loops):"0" (loops));
}
int main(void)
{
    /*  Set GPB5,GPB6,GPB8,GPB10 as GPIO mode(0x01) */
    GPBCON = (GPBCON|0x333C00)&0x111400;
    GPBUP = (GPBUP | 0x560);
    while(1)
    {
        /* Set GPB5,GPB6,GPB8,GPB10 as high level, to turn LED0,LED1,LED2,LED3 off */
        GPBDAT = (GPBDAT | 0x560);
        delay(DELAY_TIME);
        /* Turn LED0 on */
        GPBDAT = (GPBDAT & (~(1<<LED0)) );
        delay(DELAY_TIME);
        /* Turn LED1 on */
        GPBDAT = (GPBDAT & (~(1<<LED1)) );
        delay(DELAY_TIME);
        /* Turn LED2 on */
        GPBDAT = (GPBDAT & (~(1<<LED2)) );
        delay(DELAY_TIME);
        /* Turn LED3 on */
        GPBDAT = (GPBDAT & (~(1<<LED3)) );
        delay(DELAY_TIME);
    }
}
linux-bsp/asm-study/asm/c_led/led.lds
New file
@@ -0,0 +1,29 @@
/***********************************************************************
 *        File:  led.lds
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  Cross tool link text, refer to u-boot.lds
 *   ChangeLog:  1, Release initial version on "Mon Mar 21 21:09:52 CST 2011"
 *
 ***********************************************************************/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(main)
SECTIONS{
    . = 0x33000000;
    .text : {
        *(.text)
        *(.rodata)
    }
    .data ALIGN(4): {
        *(.data)
    }
    .bss ALIGN(4): {
        *(.bss)
    }
}
linux-bsp/asm-study/asm/c_led/makefile
New file
@@ -0,0 +1,51 @@
# ***********************************************************************
# *        File:  makefile
# *     Version:  1.0.0
# *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
# * Description:  Makefile used to cross compile the ASM and C source code
# *   ChangeLog:  1, Release initial version on "Mon Mar 21 21:09:52 CST 2011"
# *
# ***********************************************************************
BINAME = led
TEXTBASE = 0x33000000
CROSS = /opt/xtools/arm920t/bin/arm-linux-
CC      = $(CROSS)gcc
LD      = $(CROSS)ld
AR      = $(CROSS)ar
OBJCOPY = $(CROSS)objcopy
OBJDUMP = $(CROSS)objdump
STRIP   = $(CROSS)strip
READELF = $(CROSS)readelf
CFLAGS  = -g -O2 -Wall -nostdinc -nostdlib -fno-builtin
AFLAGS  = $(CFLAGS) -D__ASSEMBLY__
LDSCRIPT = ${BINAME}.lds
LDFLAGS  = -T $(LDSCRIPT) -Ttext $(TEXTBASE)
SRC_C   = $(wildcard *.c)
SRC_S   = $(wildcard *.S)
OBJ_C   = $(patsubst %.c,%.o,$(SRC_C))
OBJ_S   = $(patsubst %.S,%.o,$(SRC_S))
OBJ_ALL = $(OBJ_C) $(OBJ_S)
.PHONY : all
all: ${OBJ_ALL}
    ${LD} $(LDFLAGS) -o ${BINAME}.elf ${OBJ_ALL}
    ${OBJCOPY} -O binary -S ${BINAME}.elf ${BINAME}.bin
    rm -f *.elf *.o
%.o: %.S
            $(CC) $(AFLAGS) -c -o $@ $<
%.o: %.c
            $(CC) $(CFLAGS) -c -o $@ $<
install:
    cp ${BINAME}.bin ~/winxp -f --reply=yes
clean:
    rm -f *.elf *.o
    rm -f ${BINAME}.bin
linux-bsp/asm-study/myboot/bignum.c
New file
@@ -0,0 +1,1842 @@
/*
 *  Multi-precision integer library
 *
 *  Copyright (C) 2006  Christophe Devine
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License, version 2.1 as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *  MA  02110-1301  USA
 */
/*
 *  This MPI implementation is based on:
 *
 *  http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf
 *  http://math.libtomcrypt.com/files/tommath.pdf
 */
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE 1
#endif
#include <common.h>
#include <bignum.h>
/*
 * Bits/chars to # of limbs conversion
 */
#define BITS_TO_LIMBS(i)  (((i) + biL - 1) / biL)
#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL)
/*
 * Initialize one or more mpi
 */
void mpi_init( mpi *X, ... )
{
    va_list args;
    va_start( args, X );
    while( X != NULL )
    {
        memset( X, 0, sizeof( mpi ) );
        X = va_arg( args, mpi* );
    }
    va_end( args );
}
/*
 * Unallocate one or more mpi
 */
void mpi_free( mpi *X, ... )
{
    va_list args;
    va_start( args, X );
    while( X != NULL )
    {
        if( X->p != NULL )
        {
            memset( X->p, 0, X->n * ciL );
            free( X->p );
        }
        memset( X, 0, sizeof( mpi ) );
        X = va_arg( args, mpi* );
    }
    va_end( args );
}
/*
 * Enlarge X to the specified # of limbs
 */
int mpi_grow( mpi *X, int nblimbs )
{
    int n = X->n;
    if( n < nblimbs )
    {
        if( X->s == 0 )
            X->s = 1;
        X->n = nblimbs;
        X->p = (t_int *) realloc( X->p, X->n * ciL );
        if( X->p == NULL )
            return( 1 );
        memset( X->p + n, 0, ( X->n - n ) * ciL );
    }
    return( 0 );
}
/*
 * Copy the contents of Y into X
 */
int mpi_copy( mpi *X, mpi *Y )
{
    int ret, i;
    if( X == Y )
        return( 0 );
    for( i = Y->n - 1; i > 0; i-- )
        if( Y->p[i] != 0 )
            break;
    i++;
    X->s = Y->s;
    CHK( mpi_grow( X, i ) );
    memset( X->p, 0, X->n * ciL );
    memcpy( X->p, Y->p, i * ciL );
cleanup:
    return( ret );
}
/*
 * Swap the contents of X and Y
 */
void mpi_swap( mpi *X, mpi *Y )
{
    mpi T;
    memcpy( &T, X , sizeof( mpi ) );
    memcpy( X , Y , sizeof( mpi ) );
    memcpy( Y , &T, sizeof( mpi ) );
}
/*
 * Set value from integer
 */
int mpi_lset( mpi *X, int z )
{
    int ret;
    CHK( mpi_grow( X, 1 ) );
    memset( X->p, 0, X->n * ciL );
    X->p[0] = ( z < 0 ) ? -z : z;
    X->s    = ( z < 0 ) ? -1 : 1;
cleanup:
    return( ret );
}
/*
 * Convert an ASCII character to digit value
 */
static int mpi_get_digit( t_int *d, int radix, char c )
{
    *d = 16;
    if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30;
    if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37;
    if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57;
    if( *d >= (t_int) radix )
        return( ERR_MPI_INVALID_CHARACTER );
    return( 0 );
}
/*
 * Set value from string
 */
int mpi_read( mpi *X, char *s, int radix )
{
    int ret, i, j, n;
    t_int d;
    mpi T;
    if( radix < 2 || radix > 16 )
        return( ERR_MPI_INVALID_PARAMETER );
    mpi_init( &T, NULL );
    if( radix == 16 )
    {
        n = BITS_TO_LIMBS( strlen(s) << 2 );
        CHK( mpi_grow( X, n ) );
        CHK( mpi_lset( X, 0 ) );
        for( i = strlen( s ) - 1, j = 0; i >= 0; i--, j++ )
        {
            if( i == 0 && s[i] == '-' )
            {
                X->s = -1;
                break;
            }
            CHK( mpi_get_digit( &d, radix, s[i] ) );
            X->p[j / (ciL * 2)] |= d << ( (j % (ciL * 2)) << 2 );
        }
    }
    else
    {
        CHK( mpi_lset( X, 0 ) );
        for( i = 0; i < (int) strlen( s ); i++ )
        {
            if( i == 0 && s[i] == '-' )
            {
                X->s = -1;
                continue;
            }
            CHK( mpi_get_digit( &d, radix, s[i] ) );
            CHK( mpi_mul_int( &T, X, radix ) );
            CHK( mpi_add_int( X, &T, d ) );
        }
    }
cleanup:
    mpi_free( &T, NULL );
    return( ret );
}
/*
 * Helper to display the digits high-order first
 */
static int mpi_recurse_showf( mpi *X, int radix, FILE *fout )
{
    int ret;
    t_int r;
    if( radix < 2 || radix > 16 )
        return( ERR_MPI_INVALID_PARAMETER );
    CHK( mpi_mod_int( &r, X, radix ) );
    CHK( mpi_div_int( X, NULL, X, radix ) );
    if( mpi_cmp_int( X, 0 ) != 0 )
        CHK( mpi_recurse_showf( X, radix, fout ) );
    if( fout != NULL )
        fprintf( fout, "%c", ( r < 10 ) ? ( (char) r + 0x30 )
                                        : ( (char) r + 0x37 ) );
    else
        printf( "%c", ( r < 10 ) ? ( (char) r + 0x30 )
                                 : ( (char) r + 0x37 ) );
cleanup:
    return( ret );
}
/*
 * Print the value of X into fout
 */
int mpi_showf( char *name, mpi *X, int radix, FILE *fout )
{
    int ret, i, j, k, l;
    mpi T;
    if( radix < 2 || radix > 16 )
        return( ERR_MPI_INVALID_PARAMETER );
    mpi_init( &T, NULL );
    if( fout != NULL )
        fprintf( fout, "%s%c", name, ( X->s == -1 ) ? '-' : ' ' );
    else
        printf( "%s%c", name, ( X->s == -1 ) ? '-' : ' ' );
    if( radix == 16 )
    {
        ret = 0;
        for( i = X->n - 1, l = 0; i >= 0; i-- )
        {
            for( j = ciL - 1; j >= 0; j-- )
            {
                k = ( X->p[i] >> (j << 3) ) & 0xFF;
                if( k == 0 && l == 0 && (i + j) != 0 )
                    continue;
                if( fout != NULL )
                    fprintf( fout, "%02X", k );
                else
                    printf( "%02X", k );
                l = 1;
            }
        }
    }
    else
    {
        CHK( mpi_copy( &T, X ) );
        CHK( mpi_recurse_showf( &T, radix, fout ) );
    }
    if( fout != NULL )
        fprintf( fout, "\n" );
    else
        printf( "\n" );
cleanup:
    mpi_free( &T, NULL );
    return( ret );
}
/*
 * Print the value of X on the console
 */
int mpi_show( char *name, mpi *X, int radix )
{
    return( mpi_showf( name, X, radix, NULL ) );
}
/*
 * Import an unsigned value from binary data
 */
int mpi_import( mpi *X, unsigned char *buf, int buflen )
{
    int ret, i, j, n;
    for( n = 0; n < buflen; n++ )
        if( buf[n] != 0 )
            break;
    CHK( mpi_grow( X, CHARS_TO_LIMBS(buflen - n) ) );
    CHK( mpi_lset( X, 0 ) );
    for( i = buflen - 1, j = 0; i >= n; i--, j++ )
        X->p[j / ciL] |= (t_int) buf[i] << ((j % ciL ) << 3);
cleanup:
    return( ret );
}
/*
 * Export an unsigned value into binary data
 */
int mpi_export( mpi *X, unsigned char *buf, int *buflen )
{
    int i, j, n, ilen;
    n = ( mpi_size( X ) + 7 ) >> 3;
    ilen = n;
    if( *buflen < n )
    {
        *buflen = n;
        return( ERR_MPI_BUFFER_TOO_SMALL );
    }
    //*buflen = ilen;
    memset( buf, 0, *buflen );
    for( i = *buflen - 1, j = 0; n > 0; i--, j++, n-- )
        buf[i] = (unsigned char) (X->p[j / ciL] >> ((j % ciL) << 3));
    return( 0 );
}
/*
 * Return the actual size in bits (without leading 0s)
 */
int mpi_size( mpi *X )
{
    int i, j;
    for( i = X->n - 1; i > 0; i-- )
        if( X->p[i] != 0 )
            break;
    for( j = biL - 1; j >= 0; j-- )
        if( ( ( X->p[i] >> j ) & 1 ) != 0 )
            break;
    return( ( i * biL ) + j + 1 );
}
/*
 * Return the number of least significant bits
 */
int mpi_lsb( mpi *X )
{
    int i, j, count = 0;
    for( i = 0; i < X->n; i++ )
        for( j = 0; j < (int) biL; j++, count++ )
            if( ( ( X->p[i] >> j ) & 1 ) != 0 )
                return( count );
    return( 0 );
}
/*
 * Left-shift: X <<= count
 */
int mpi_shift_l( mpi *X, int count )
{
    int ret, i, v0, t1;
    t_int r0 = 0, r1;
    v0 = count /  biL;
    t1 = count & (biL - 1);
    i = mpi_size( X ) + count;
    if( X->n * (int) biL < i )
        CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) );
    ret = 0;
    /*
     * shift by count / limb_size
     */
    if( v0 > 0 )
    {
        for( i = X->n - 1; i >= v0; i-- )
            X->p[i] = X->p[i - v0];
        for( ; i >= 0; i-- )
            X->p[i] = 0;
    }
    /*
     * shift by count % limb_size
     */
    if( t1 > 0 )
    {
        for( i = v0; i < X->n; i++ )
        {
            r1 = X->p[i] >> (biL - t1);
            X->p[i] <<= t1;
            X->p[i] |= r0;
            r0 = r1;
        }
    }
cleanup:
    return( ret );
}
/*
 * Right-shift: X >>= count
 */
int mpi_shift_r( mpi *X, int count )
{
    int i, v0, v1;
    t_int r0 = 0, r1;
    v0 = count /  biL;
    v1 = count & (biL - 1);
    /*
     * shift by count / limb_size
     */
    if( v0 > 0 )
    {
        for( i = 0; i < X->n - v0; i++ )
            X->p[i] = X->p[i + v0];
        for( ; i < X->n; i++ )
            X->p[i] = 0;
    }
    /*
     * shift by count % limb_size
     */
    if( v1 > 0 )
    {
        for( i = X->n - 1; i >= 0; i-- )
        {
            r1 = X->p[i] << (biL - v1);
            X->p[i] >>= v1;
            X->p[i] |= r0;
            r0 = r1;
        }
    }
    return( 0 );
}
/*
 * Compare unsigned values
 */
int mpi_cmp_abs( mpi *X, mpi *Y )
{
    int i, j;
    for( i = X->n - 1; i >= 0; i-- )
        if( X->p[i] != 0 )
            break;
    for( j = Y->n - 1; j >= 0; j-- )
        if( Y->p[j] != 0 )
            break;
    if( i < 0 && j < 0 )
        return( 0 );
    if( i > j ) return(  1 );
    if( j > i ) return( -1 );
    for( ; i >= 0; i-- )
    {
        if( X->p[i] > Y->p[i] ) return(  1 );
        if( X->p[i] < Y->p[i] ) return( -1 );
    }
    return( 0 );
}
/*
 * Compare signed values
 */
int mpi_cmp_mpi( mpi *X, mpi *Y )
{
    int i, j;
    for( i = X->n - 1; i >= 0; i-- )
        if( X->p[i] != 0 )
            break;
    for( j = Y->n - 1; j >= 0; j-- )
        if( Y->p[j] != 0 )
            break;
    if( i < 0 && j < 0 )
        return( 0 );
    if( i > j ) return(  X->s );
    if( j > i ) return( -X->s );
    if( X->s > 0 && Y->s < 0 ) return(  1 );
    if( Y->s > 0 && X->s < 0 ) return( -1 );
    for( ; i >= 0; i-- )
    {
        if( X->p[i] > Y->p[i] ) return(  X->s );
        if( X->p[i] < Y->p[i] ) return( -X->s );
    }
    return( 0 );
}
/*
 * Compare signed values
 */
int mpi_cmp_int( mpi *X, int z )
{
    mpi Y;
    t_int p[1];
    *p  = ( z < 0 ) ? -z : z;
    Y.s = ( z < 0 ) ? -1 : 1;
    Y.n = 1;
    Y.p = p;
    return( mpi_cmp_mpi( X, &Y ) );
}
/*
 * Unsigned addition: X = |A| + |B|  (HAC 14.7)
 */
int mpi_add_abs( mpi *X, mpi *A, mpi *B )
{
    int ret, i, j;
    t_int *o, *p, c;
    if( X == B )
    {
        mpi *T = A; A = X; B = T;
    }
    if( X != A )
        CHK( mpi_copy( X, A ) );
    for( j = B->n - 1; j >= 0; j-- )
        if( B->p[j] != 0 )
            break;
    CHK( mpi_grow( X, j + 1 ) );
    o = B->p; p = X->p; c = 0;
    for( i = 0; i <= j; i++, o++, p++ )
    {
        *p +=  c; c  = ( *p <  c );
        *p += *o; c += ( *p < *o );
    }
    while( c != 0 )
    {
        if( i >= X->n )
        {
            CHK( mpi_grow( X, i + 1 ) );
            p = X->p + i;
        }
        *p += c; c = ( *p < c ); i++;
    }
cleanup:
    return( ret );
}
/*
 * Helper for mpi substraction
 */
static void mpi_sub_hlp( int n, t_int *s, t_int *d )
{
    int i;
    t_int c, z;
    for( i = c = 0; i < n; i++, s++, d++ )
    {
        z = ( *d <  c );     *d -=  c;
        c = ( *d < *s ) + z; *d -= *s;
    }
    while( c != 0 )
    {
        z = ( *d < c ); *d -= c;
        c = z; i++; d++;
    }
}
/*
 * Unsigned substraction: X = |A| - |B|  (HAC 14.9)
 */
int mpi_sub_abs( mpi *X, mpi *A, mpi *B )
{
    mpi TB;
    int ret, n;
    if( mpi_cmp_abs( A, B ) < 0 )
        return( ERR_MPI_NEGATIVE_VALUE );
    mpi_init( &TB, NULL );
    if( X == B )
    {
        CHK( mpi_copy( &TB, B ) );
        B = &TB;
    }
    if( X != A )
        CHK( mpi_copy( X, A ) );
    ret = 0;
    for( n = B->n - 1; n >= 0; n-- )
        if( B->p[n] != 0 )
            break;
    mpi_sub_hlp( n + 1, B->p, X->p );
cleanup:
    mpi_free( &TB, NULL );
    return( ret );
}
/*
 * Signed addition: X = A + B
 */
int mpi_add_mpi( mpi *X, mpi *A, mpi *B )
{
    int ret, s = A->s;
    if( A->s * B->s < 0 )
    {
        if( mpi_cmp_abs( A, B ) >= 0 )
        {
            CHK( mpi_sub_abs( X, A, B ) );
            X->s =  s;
        }
        else
        {
            CHK( mpi_sub_abs( X, B, A ) );
            X->s = -s;
        }
    }
    else
    {
        CHK( mpi_add_abs( X, A, B ) );
        X->s = s;
    }
cleanup:
    return( ret );
}
/*
 * Signed substraction: X = A - B
 */
int mpi_sub_mpi( mpi *X, mpi *A, mpi *B )
{
    int ret, s = A->s;
    if( A->s * B->s > 0 )
    {
        if( mpi_cmp_abs( A, B ) >= 0 )
        {
            CHK( mpi_sub_abs( X, A, B ) );
            X->s =  s;
        }
        else
        {
            CHK( mpi_sub_abs( X, B, A ) );
            X->s = -s;
        }
    }
    else
    {
        CHK( mpi_add_abs( X, A, B ) );
        X->s = s;
    }
cleanup:
    return( ret );
}
/*
 * Signed addition: X = A + b
 */
int mpi_add_int( mpi *X, mpi *A, int b )
{
    mpi _B;
    t_int p[1];
    p[0] = ( b < 0 ) ? -b : b;
    _B.s = ( b < 0 ) ? -1 : 1;
    _B.n = 1;
    _B.p = p;
    return( mpi_add_mpi( X, A, &_B ) );
}
/*
 * Signed substraction: X = A - b
 */
int mpi_sub_int( mpi *X, mpi *A, int b )
{
    mpi _B;
    t_int p[1];
    p[0] = ( b < 0 ) ? -b : b;
    _B.s = ( b < 0 ) ? -1 : 1;
    _B.n = 1;
    _B.p = p;
    return( mpi_sub_mpi( X, A, &_B ) );
}
/*
 * Helper for mpi multiplication
 */
static void mpi_mul_hlp( int i, t_int *s, t_int *d, t_int b )
{
    t_int c = 0;
#if defined(MULADDC_HUIT)
    for( ; i >= 8; i -= 8 )
    {
        MULADDC_INIT
        MULADDC_HUIT
        MULADDC_STOP
    }
    for( ; i > 0; i-- )
    {
        MULADDC_INIT
        MULADDC_CORE
        MULADDC_STOP
    }
#else
    if( i == 32 )
    {
        MULADDC_INIT
        MULADDC_CORE   MULADDC_CORE
        MULADDC_CORE   MULADDC_CORE   MULADDC_CORE
        MULADDC_CORE   MULADDC_CORE   MULADDC_CORE
        MULADDC_CORE   MULADDC_CORE
        MULADDC_CORE   MULADDC_CORE   MULADDC_CORE
        MULADDC_CORE   MULADDC_CORE   MULADDC_CORE
        MULADDC_CORE   MULADDC_CORE   MULADDC_CORE
        MULADDC_CORE   MULADDC_CORE   MULADDC_CORE
        MULADDC_CORE   MULADDC_CORE
        MULADDC_CORE   MULADDC_CORE   MULADDC_CORE
        MULADDC_CORE   MULADDC_CORE   MULADDC_CORE
        MULADDC_CORE   MULADDC_CORE
        MULADDC_STOP
    }
    else
    {
        if( i == 16 )
        {
            MULADDC_INIT
            MULADDC_CORE   MULADDC_CORE
            MULADDC_CORE   MULADDC_CORE
            MULADDC_CORE   MULADDC_CORE
            MULADDC_CORE   MULADDC_CORE
            MULADDC_CORE   MULADDC_CORE
            MULADDC_CORE   MULADDC_CORE
            MULADDC_CORE   MULADDC_CORE
            MULADDC_CORE   MULADDC_CORE
            MULADDC_STOP
        }
        else
        {
            for( ; i >= 8; i -= 8 )
            {
                MULADDC_INIT
                MULADDC_CORE   MULADDC_CORE
                MULADDC_CORE   MULADDC_CORE
                MULADDC_CORE   MULADDC_CORE
                MULADDC_CORE   MULADDC_CORE
                MULADDC_STOP
            }
            for( ; i > 0; i-- )
            {
                MULADDC_INIT
                MULADDC_CORE
                MULADDC_STOP
            }
        }
    }
#endif
    do {
        *d += c; c = ( *d < c ); d++;
    }
    while( c != 0 );
}
/*
 * Baseline multiplication: X = A * B  (HAC 14.12)
 */
int mpi_mul_mpi( mpi *X, mpi *A, mpi *B )
{
    int ret, i, j;
    mpi TA, TB;
    mpi_init( &TA, &TB, NULL );
    if( X == A ) { CHK( mpi_copy( &TA, A ) ); A = &TA; }
    if( X == B ) { CHK( mpi_copy( &TB, B ) ); B = &TB; }
    for( i = A->n - 1; i >= 0; i-- )
        if( A->p[i] != 0 )
            break;
    for( j = B->n - 1; j >= 0; j-- )
        if( B->p[j] != 0 )
            break;
    CHK( mpi_grow( X, i + j + 2 ) );
    CHK( mpi_lset( X, 0 ) );
    for( i++; j >= 0; j-- )
        mpi_mul_hlp( i, A->p, X->p + j, B->p[j] );
    X->s = A->s * B->s;
cleanup:
    mpi_free( &TB, &TA, NULL );
    return( ret );
}
/*
 * Baseline multiplication: X = A * b
 */
int mpi_mul_int( mpi *X, mpi *A, t_int b )
{
    mpi _B;
    t_int p[1];
    _B.s = 1;
    _B.n = 1;
    _B.p = p;
    p[0] = b;
    return( mpi_mul_mpi( X, A, &_B ) );
}
/*
 * Division by mpi: A = Q * B + R  (HAC 14.20)
 */
int mpi_div_mpi( mpi *Q, mpi *R, mpi *A, mpi *B )
{
    int ret, i, n, t, k;
    mpi X, Y, Z, T1, T2;
    if( mpi_cmp_int( B, 0 ) == 0 )
        return( ERR_MPI_DIVISION_BY_ZERO );
    mpi_init( &X, &Y, &Z, &T1, &T2, NULL );
    if( mpi_cmp_abs( A, B ) < 0 )
    {
        if( Q != NULL ) CHK( mpi_lset( Q, 0 ) );
        if( R != NULL ) CHK( mpi_copy( R, A ) );
        return( 0 );
    }
    CHK( mpi_copy( &X, A ) );
    CHK( mpi_copy( &Y, B ) );
    X.s = Y.s = 1;
    CHK( mpi_grow( &Z, A->n + 2 ) );
    CHK( mpi_lset( &Z,  0 ) );
    CHK( mpi_grow( &T1, 2 ) );
    CHK( mpi_grow( &T2, 3 ) );
    k = mpi_size( &Y ) % biL;
    if( k < (int) biL - 1 )
    {
        k = biL - 1 - k;
        CHK( mpi_shift_l( &X, k ) );
        CHK( mpi_shift_l( &Y, k ) );
    }
    else k = 0;
    n = X.n - 1;
    t = Y.n - 1;
    mpi_shift_l( &Y, biL * (n - t) );
    while( mpi_cmp_mpi( &X, &Y ) >= 0 )
    {
        Z.p[n - t]++;
        mpi_sub_mpi( &X, &X, &Y );
    }
    mpi_shift_r( &Y, biL * (n - t) );
    for( i = n; i > t ; i-- )
    {
        if( X.p[i] >= Y.p[t] )
            Z.p[i - t - 1] = ~0;
        else
        {
#if defined(HAVE_LONGLONG)
            t_dbl r;
            r  = (t_dbl) X.p[i] << biL;
            r |= (t_dbl) X.p[i - 1];
            r /= Y.p[t];
            if( r > ((t_dbl) 1 << biL) - 1)
                r = ((t_dbl) 1 << biL) - 1;
            Z.p[i - t - 1] = (t_int) r;
#else
            /*
             * __udiv_qrnnd_c, from GMP/longlong.h
             */
            t_int q0, q1, r0, r1;
            t_int d0, d1, d, m;
            d  = Y.p[t];
            d0 = ( d << biH ) >> biH;
            d1 = ( d >> biH );
            q1 = X.p[i] / d1;
            r1 = X.p[i] - d1 * q1;
            r1 <<= biH;
            r1 |= ( X.p[i - 1] >> biH );
            m = q1 * d0;
            if( r1 < m )
            {
                q1--, r1 += d;
                while( r1 >= d && r1 < m )
                    q1--, r1 += d;
            }
            r1 -= m;
            q0 = r1 / d1;
            r0 = r1 - d1 * q0;
            r0 <<= biH;
            r0 |= ( X.p[i - 1] << biH ) >> biH;
            m = q0 * d0;
            if( r0 < m )
            {
                q0--, r0 += d;
                while( r0 >= d && r0 < m )
                    q0--, r0 += d;
            }
            r0 -= m;
            Z.p[i - t - 1] = ( q1 << biH ) | q0;
#endif
        }
        Z.p[i - t - 1]++;
        do
        {
            Z.p[i - t - 1]--;
            CHK( mpi_lset( &T1, 0 ) );
            T1.p[0] = (t < 1) ? 0 : Y.p[t - 1];
            T1.p[1] = Y.p[t];
            CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) );
            CHK( mpi_lset( &T2, 0 ) );
            T2.p[0] = (i < 2) ? 0 : X.p[i - 2];
            T2.p[1] = (i < 1) ? 0 : X.p[i - 1];
            T2.p[2] = X.p[i];
        }
        while( mpi_cmp_mpi( &T1, &T2 ) > 0 );
        CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) );
        CHK( mpi_shift_l( &T1,  biL * (i - t - 1) ) );
        CHK( mpi_sub_mpi( &X, &X, &T1 ) );
        if( mpi_cmp_int( &X, 0 ) < 0 )
        {
            CHK( mpi_copy( &T1, &Y ) );
            CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) );
            CHK( mpi_add_mpi( &X, &X, &T1 ) );
            Z.p[i - t - 1]--;
        }
    }
    if( Q != NULL )
    {
        mpi_copy( Q, &Z );
        Q->s = A->s * B->s;
    }
    if( R != NULL )
    {
        mpi_shift_r( &X, k );
        mpi_copy( R, &X );
        R->s = A->s;
        if( mpi_cmp_int( R, 0 ) == 0 )
            R->s = 1;
    }
cleanup:
    mpi_free( &X, &Y, &Z, &T1, &T2, NULL );
    return( ret );
}
/*
 * Division by int: A = Q * b + R
 *
 * Returns 0 if successful
 *         1 if memory allocation failed
 *         ERR_MPI_DIVISION_BY_ZERO if b == 0
 */
int mpi_div_int( mpi *Q, mpi *R, mpi *A, int b )
{
    mpi _B;
    t_int p[1];
    p[0] = ( b < 0 ) ? -b : b;
    _B.s = ( b < 0 ) ? -1 : 1;
    _B.n = 1;
    _B.p = p;
    return( mpi_div_mpi( Q, R, A, &_B ) );
}
/*
 * Modulo: R = A mod B
 */
int mpi_mod_mpi( mpi *R, mpi *A, mpi *B )
{
    int ret;
    CHK( mpi_div_mpi( NULL, R, A, B ) );
    while( mpi_cmp_int( R, 0 ) < 0 )
      CHK( mpi_add_mpi( R, R, B ) );
    while( mpi_cmp_mpi( R, B ) >= 0 )
      CHK( mpi_sub_mpi( R, R, B ) );
cleanup:
    return( ret );
}
/*
 * Modulo: r = A mod b
 */
int mpi_mod_int( t_int *r, mpi *A, int b )
{
    int i;
    t_int x, y, z;
    if( b == 0 )
        return( ERR_MPI_DIVISION_BY_ZERO );
    if( b < 0 )
        b = -b;
    /*
     * handle trivial cases
     */
    if( b == 1 ) { *r = 0;           return( 0 ); }
    if( b == 2 ) { *r = A->p[0] & 1; return( 0 ); }
    /*
     * general case
     */
    for( i = A->n - 1, y = 0; i >= 0; i-- )
    {
        x  = A->p[i];
        y  = ( y << biH ) | ( x >> biH );
        z  = y / b;
        y -= z * b;
        x <<= biH;
        y  = ( y << biH ) | ( x >> biH );
        z  = y / b;
        y -= z * b;
    }
    *r = y;
    return( 0 );
}
/*
 * Fast Montgomery initialization (thanks to Tom St Denis)
 */
static void mpi_montg_init( t_int *mm, mpi *N )
{
    t_int x, m0 = N->p[0];
    x  = m0;
    x += ((m0 + 2) & 4) << 1;
    x *= (2 - (m0 * x));
    if( biL >= 16 ) x *= (2 - (m0 * x));
    if( biL >= 32 ) x *= (2 - (m0 * x));
    if( biL >= 64 ) x *= (2 - (m0 * x));
    *mm = ~x + 1;
}
/*
 * Montgomery multiplication: A = A * B * R^-1 mod N  (HAC 14.36)
 */
static void mpi_montmul( mpi *A, mpi *B, mpi *N, t_int mm, mpi *T )
{
    int i, n, m;
    t_int u0, u1, *d;
    memset( T->p, 0, ciL * T->n );
    d = T->p;
    n = N->n;
    m = ( B->n < n ) ? B->n : n;
    for( i = 0; i < n; i++ )
    {
        /*
         * T = (T + u0*B + u1*N) / 2^biL
         */
        u0 = A->p[i];
        u1 = ( d[0] + u0 * B->p[0] ) * mm;
        mpi_mul_hlp( m, B->p, d, u0 );
        mpi_mul_hlp( n, N->p, d, u1 );
        *d++ = u0; d[n + 1] = 0;
    }
    memcpy( A->p, d, ciL * (n + 1) );
    if( mpi_cmp_abs( A, N ) >= 0 )
        mpi_sub_hlp( n, N->p, A->p );
    else
        /* prevent timing attacks */
        mpi_sub_hlp( n, A->p, T->p );
}
/*
 * Montgomery reduction: A = A * R^-1 mod N
 */
static void mpi_montred( mpi *A, mpi *N, t_int mm, mpi *T )
{
    t_int z = 1;
    mpi U;
    U.n = U.s = z;
    U.p = &z;
    mpi_montmul( A, &U, N, mm, T );
}
/*
 * Sliding-window exponentiation: X = A^E mod N  (HAC 14.85)
 */
int mpi_exp_mod( mpi *X, mpi *A, mpi *E, mpi *N, mpi *_RR )
{
    int ret, i, j, wsize, wbits;
    int bufsize, nblimbs, nbits;
    t_int ei, mm, state;
    mpi RR, T, W[64];
    if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 )
        return( ERR_MPI_INVALID_PARAMETER );
    /*
     * Init temps and window size
     */
    mpi_montg_init( &mm, N );
    mpi_init( &RR, &T, NULL );
    memset( W, 0, sizeof( W ) );
    i = mpi_size( E );
    wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 :
            ( i >  79 ) ? 4 : ( i >  23 ) ? 3 : 1;
    j = N->n + 1;
    CHK( mpi_grow( X, j ) );
    CHK( mpi_grow( &W[1],  j ) );
    CHK( mpi_grow( &T, j * 2 ) );
    /*
     * If 1st call, pre-compute R^2 mod N
     */
    if( _RR == NULL || _RR->p == NULL )
    {
        CHK( mpi_lset( &RR, 1 ) );
        CHK( mpi_shift_l( &RR, N->n * 2 * biL ) );
        CHK( mpi_mod_mpi( &RR, &RR, N ) );
        if( _RR != NULL )
            memcpy( _RR, &RR, sizeof( mpi ) );
    }
    else
        memcpy( &RR, _RR, sizeof( mpi ) );
    /*
     * W[1] = A * R^2 * R^-1 mod N = A * R mod N
     */
    if( mpi_cmp_mpi( A, N ) >= 0 )
        mpi_mod_mpi( &W[1], A, N );
    else   mpi_copy( &W[1], A );
    mpi_montmul( &W[1], &RR, N, mm, &T );
    /*
     * X = R^2 * R^-1 mod N = R mod N
     */
    CHK( mpi_copy( X, &RR ) );
    mpi_montred( X, N, mm, &T );
    if( wsize > 1 )
    {
        /*
         * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1)
         */
        j =  1 << (wsize - 1);
        CHK( mpi_grow( &W[j], N->n + 1 ) );
        CHK( mpi_copy( &W[j], &W[1]    ) );
        for( i = 0; i < wsize - 1; i++ )
            mpi_montmul( &W[j], &W[j], N, mm, &T );
        /*
         * W[i] = W[i - 1] * W[1]
         */
        for( i = j + 1; i < (1 << wsize); i++ )
        {
            CHK( mpi_grow( &W[i], N->n + 1 ) );
            CHK( mpi_copy( &W[i], &W[i - 1] ) );
            mpi_montmul( &W[i], &W[1], N, mm, &T );
        }
    }
    nblimbs = E->n;
    bufsize = 0;
    nbits   = 0;
    wbits   = 0;
    state   = 0;
    while( 1 )
    {
        if( bufsize == 0 )
        {
            if( nblimbs-- == 0 )
                break;
            bufsize = sizeof( t_int ) << 3;
        }
        bufsize--;
        ei = (E->p[nblimbs] >> bufsize) & 1;
        /*
         * skip leading 0s
         */
        if( ei == 0 && state == 0 )
            continue;
        if( ei == 0 && state == 1 )
        {
            /*
             * out of window, square X
             */
            mpi_montmul( X, X, N, mm, &T );
            continue;
        }
        /*
         * add ei to current window
         */
        state = 2;
        nbits++;
        wbits |= (ei << (wsize - nbits));
        if( nbits == wsize )
        {
            /*
             * X = X^wsize R^-1 mod N
             */
            for( i = 0; i < wsize; i++ )
                mpi_montmul( X, X, N, mm, &T );
            /*
             * X = X * W[wbits] R^-1 mod N
             */
            mpi_montmul( X, &W[wbits], N, mm, &T );
            state--;
            nbits = 0;
            wbits = 0;
        }
    }
    /*
     * process the remaining bits
     */
    for( i = 0; i < nbits; i++ )
    {
        mpi_montmul( X, X, N, mm, &T );
        wbits <<= 1;
        if( (wbits & (1 << wsize)) != 0 )
            mpi_montmul( X, &W[1], N, mm, &T );
    }
    /*
     * X = A^E * R * R^-1 mod N = A^E mod N
     */
    mpi_montred( X, N, mm, &T );
cleanup:
    for( i = (1 << (wsize - 1)); i < (1 << wsize); i++ )
        mpi_free( &W[i], NULL );
    if( _RR != NULL )
         mpi_free( &W[1], &T, NULL );
    else mpi_free( &W[1], &T, &RR, NULL );
    return( ret );
}
/*
 * Greatest common divisor: G = gcd(A, B)  (HAC 14.54)
 */
int mpi_gcd( mpi *G, mpi *A, mpi *B )
{
    int ret, count;
    mpi TG, TA, TB;
    mpi_init( &TG, &TA, &TB, NULL );
    CHK( mpi_lset( &TG, 1 ) );
    CHK( mpi_copy( &TA, A ) );
    CHK( mpi_copy( &TB, B ) );
    TA.s = TB.s = 1;
    count = ( mpi_lsb( &TA ) < mpi_lsb( &TB ) )
            ? mpi_lsb( &TA ) : mpi_lsb( &TB );
    CHK( mpi_shift_l( &TG, count ) );
    CHK( mpi_shift_r( &TA, count ) );
    CHK( mpi_shift_r( &TB, count ) );
    while( mpi_cmp_int( &TA, 0 ) != 0 )
    {
        while( ( TA.p[0] & 1 ) == 0 ) CHK( mpi_shift_r( &TA, 1 ) );
        while( ( TB.p[0] & 1 ) == 0 ) CHK( mpi_shift_r( &TB, 1 ) );
        if( mpi_cmp_mpi( &TA, &TB ) >= 0 )
        {
            CHK( mpi_sub_abs( &TA, &TA, &TB ) );
            CHK( mpi_shift_r( &TA, 1 ) );
        }
        else
        {
            CHK( mpi_sub_abs( &TB, &TB, &TA ) );
            CHK( mpi_shift_r( &TB, 1 ) );
        }
    }
    CHK( mpi_mul_mpi( G, &TG, &TB ) );
cleanup:
    mpi_free( &TB, &TA, &TG, NULL );
    return( ret );
}
/*
 * Modular inverse: X = A^-1 mod N  (HAC 14.61 / 14.64)
 */
int mpi_inv_mod( mpi *X, mpi *A, mpi *N )
{
    int ret;
    mpi G, TA, TU, U1, U2, TB, TV, V1, V2;
    if( mpi_cmp_int( N, 0 ) <= 0 )
        return( ERR_MPI_INVALID_PARAMETER );
    mpi_init( &TA, &TU, &U1, &U2, &G,
              &TB, &TV, &V1, &V2, NULL );
    CHK( mpi_gcd( &G, A, N ) );
    if( mpi_cmp_int( &G, 1 ) != 0 )
    {
        ret = ERR_MPI_NOT_INVERTIBLE;
        goto cleanup;
    }
    CHK( mpi_mod_mpi( &TA, A, N ) );
    CHK( mpi_copy( &TU, &TA ) );
    CHK( mpi_copy( &TB, N ) );
    CHK( mpi_copy( &TV, N ) );
    CHK( mpi_lset( &U1, 1 ) );
    CHK( mpi_lset( &U2, 0 ) );
    CHK( mpi_lset( &V1, 0 ) );
    CHK( mpi_lset( &V2, 1 ) );
    do
    {
        while( ( TU.p[0] & 1 ) == 0 )
        {
            CHK( mpi_shift_r( &TU, 1 ) );
            if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 )
            {
                CHK( mpi_add_mpi( &U1, &U1, &TB ) );
                CHK( mpi_sub_mpi( &U2, &U2, &TA ) );
            }
            CHK( mpi_shift_r( &U1, 1 ) );
            CHK( mpi_shift_r( &U2, 1 ) );
        }
        while( ( TV.p[0] & 1 ) == 0 )
        {
            CHK( mpi_shift_r( &TV, 1 ) );
            if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 )
            {
                CHK( mpi_add_mpi( &V1, &V1, &TB ) );
                CHK( mpi_sub_mpi( &V2, &V2, &TA ) );
            }
            CHK( mpi_shift_r( &V1, 1 ) );
            CHK( mpi_shift_r( &V2, 1 ) );
        }
        if( mpi_cmp_mpi( &TU, &TV ) >= 0 )
        {
            CHK( mpi_sub_mpi( &TU, &TU, &TV ) );
            CHK( mpi_sub_mpi( &U1, &U1, &V1 ) );
            CHK( mpi_sub_mpi( &U2, &U2, &V2 ) );
        }
        else
        {
            CHK( mpi_sub_mpi( &TV, &TV, &TU ) );
            CHK( mpi_sub_mpi( &V1, &V1, &U1 ) );
            CHK( mpi_sub_mpi( &V2, &V2, &U2 ) );
        }
    }
    while( mpi_cmp_int( &TU, 0 ) != 0 );
    while( mpi_cmp_int( &V1, 0 ) < 0 )
      CHK( mpi_add_mpi( &V1, &V1, N ) );
    while( mpi_cmp_mpi( &V1, N ) >= 0 )
      CHK( mpi_sub_mpi( &V1, &V1, N ) );
    CHK( mpi_copy( X, &V1 ) );
cleanup:
    mpi_free( &V2, &V1, &TV, &TB, &G,
              &U2, &U1, &TU, &TA, NULL );
    return( ret );
}
#if !defined(NO_GENPRIME)
static const int small_prime[] =
{
       3,  113,  271,  443,  619,  821,  1013,  1213,
       5,  127,  277,  449,  631,  823,  1019,  1217,
       7,  131,  281,  457,  641,  827,  1021,  1223,
      11,  137,  283,  461,  643,  829,  1031,  1229,
      13,  139,  293,  463,  647,  839,  1033,  1231,
      17,  149,  307,  467,  653,  853,  1039,  1237,
      19,  151,  311,  479,  659,  857,  1049,  1249,
      23,  157,  313,  487,  661,  859,  1051,  1259,
      29,  163,  317,  491,  673,  863,  1061,  1277,
      31,  167,  331,  499,  677,  877,  1063,  1279,
      37,  173,  337,  503,  683,  881,  1069,  1283,
      41,  179,  347,  509,  691,  883,  1087,  1289,
      43,  181,  349,  521,  701,  887,  1091,  1291,
      47,  191,  353,  523,  709,  907,  1093,  1297,
      53,  193,  359,  541,  719,  911,  1097,  1301,
      59,  197,  367,  547,  727,  919,  1103,  1303,
      61,  199,  373,  557,  733,  929,  1109,  1307,
      67,  211,  379,  563,  739,  937,  1117,  1319,
      71,  223,  383,  569,  743,  941,  1123,  1321,
      73,  227,  389,  571,  751,  947,  1129,  1327,
      79,  229,  397,  577,  757,  953,  1151,  1361,
      83,  233,  401,  587,  761,  967,  1153,  1367,
      89,  239,  409,  593,  769,  971,  1163,  1373,
      97,  241,  419,  599,  773,  977,  1171,  1381,
     101,  251,  421,  601,  787,  983,  1181,  1399,
     103,  257,  431,  607,  797,  991,  1187,  1409,
     107,  263,  433,  613,  809,  997,  1193,  1423,
     109,  269,  439,  617,  811, 1009,  1201,  -110
};
/*
 * Miller-Rabin primality test  (HAC 4.24)
 */
int mpi_is_prime( mpi *X )
{
    int ret, i, j, s, xs;
    mpi W, R, T, A, RR;
    if( mpi_cmp_int( X, 0 ) == 0 )
        return( 0 );
    mpi_init( &W, &R, &T, &A, &RR, NULL );
    xs = X->s; X->s = 1;
    /*
     * test trivial factors first
     */
    if( ( X->p[0] & 1 ) == 0 )
        return( ERR_MPI_IS_COMPOSITE );
    for( i = 0; small_prime[i] > 0; i++ )
    {
        t_int r;
        if( mpi_cmp_int( X, small_prime[i] ) <= 0 )
            return( 0 );
        CHK( mpi_mod_int( &r, X, small_prime[i] ) );
        if( r == 0 )
            return( ERR_MPI_IS_COMPOSITE );
    }
    /*
     * W = |X| - 1
     * R = W >> lsb( W )
     */
    CHK( mpi_sub_int( &W, X, 1 ) );
    CHK( mpi_copy( &R, &W ) );
    CHK( mpi_shift_r( &R, s = mpi_lsb( &W ) ) );
    for( i = 0; i < 8; i++ )
    {
        /*
         * pick a random A, 1 < A < |X| - 1
         */
        CHK( mpi_grow( &A, X->n ) );
        for( j = 0; j < A.n; j++ )
            A.p[j] = (t_int) rand() * rand();
        CHK( mpi_shift_r( &A, mpi_size( &A ) -
                              mpi_size( &W ) + 1 ) );
        A.p[0] |= 3;
        /*
         * A = A^R mod |X|
         */
        CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) );
        if( mpi_cmp_mpi( &A, &W ) == 0 ||
            mpi_cmp_int( &A,  1 ) == 0 )
            continue;
        j = 1;
        while( j < s && mpi_cmp_mpi( &A, &W ) != 0 )
        {
            /*
             * A = A * A mod |X|
             */
            CHK( mpi_mul_mpi( &T, &A, &A ) );
            CHK( mpi_mod_mpi( &A, &T, X  ) );
            if( mpi_cmp_int( &A, 1 ) == 0 )
                break;
            j++;
        }
        /*
         * not prime if A != |X| - 1 or A == 1
         */
        if( mpi_cmp_mpi( &A, &W ) != 0 || j < s )
        {
            ret = ERR_MPI_IS_COMPOSITE;
            break;
        }
    }
cleanup:
    X->s = xs;
    mpi_free( &A, &T, &R, &W, NULL );
    return( ret );
}
/*
 * Prime number generation
 */
int mpi_gen_prime( mpi *X, int nbits, int dh_flag,
                   int (*rng_f)(void *), void *rng_d )
{
    int ret, k, n;
    unsigned char *p;
    mpi Y;
    if( nbits < 3 )
        return( ERR_MPI_INVALID_PARAMETER );
    mpi_init( &Y, NULL );
    n = BITS_TO_LIMBS( nbits );
    CHK( mpi_grow( X, n ) );
    CHK( mpi_lset( X, 0 ) );
    p = (unsigned char *) X->p;
    for( k = 0; k < ciL * X->n; k++ )
        *p++ = rng_f( rng_d );
    k = mpi_size( X );
    if( k < nbits ) CHK( mpi_shift_l( X, nbits - k ) );
    if( k > nbits ) CHK( mpi_shift_r( X, k - nbits ) );
    X->p[0] |= 3;
    if( dh_flag == 0 )
    {
        while( ( ret = mpi_is_prime( X ) ) != 0 )
        {
            if( ret != ERR_MPI_IS_COMPOSITE )
                goto cleanup;
            CHK( mpi_add_int( X, X, 2 ) );
        }
    }
    else
    {
        CHK( mpi_sub_int( &Y, X, 1 ) );
        CHK( mpi_shift_r( &Y, 1 ) );
        while( 1 )
        {
            if( ( ret = mpi_is_prime( X ) ) == 0 )
            {
                if( ( ret = mpi_is_prime( &Y ) ) == 0 )
                    break;
                if( ret != ERR_MPI_IS_COMPOSITE )
                    goto cleanup;
            }
            if( ret != ERR_MPI_IS_COMPOSITE )
                goto cleanup;
            CHK( mpi_add_int( &Y, X, 1 ) );
            CHK( mpi_add_int(  X, X, 2 ) );
            CHK( mpi_shift_r( &Y, 1 ) );
        }
    }
cleanup:
    mpi_free( &Y, NULL );
    return( ret );
}
#endif
static const char _bignum_src[] = "_bignum_src";
#ifdef SELF_TEST
/*
 * Checkup routine
 */
int mpi_self_test( void )
{
    int ret;
    mpi A, E, N, X, Y, U, V;
    mpi_init( &A, &E, &N, &X, &Y, &U, &V, NULL );
    CHK( mpi_read( &A, "EFE021C2645FD1DC586E69184AF4A31E" \
                       "D5F53E93B5F123FA41680867BA110131" \
                       "944FE7952E2517337780CB0DB80E61AA" \
                       "E7C8DDC6C5C6AADEB34EB38A2F40D5E6", 16 ) );
    CHK( mpi_read( &E, "B2E7EFD37075B9F03FF989C7C5051C20" \
                       "34D2A323810251127E7BF8625A4F49A5" \
                       "F3E27F4DA8BD59C47D6DAABA4C8127BD" \
                       "5B5C25763222FEFCCFC38B832366C29E", 16 ) );
    CHK( mpi_read( &N, "0066A198186C18C10B2F5ED9B522752A" \
                       "9830B69916E535C8F047518A889A43A5" \
                       "94B6BED27A168D31D4A52F88925AA8F5", 16 ) );
    CHK( mpi_mul_mpi( &X, &A, &N ) );
    CHK( mpi_read( &U, "602AB7ECA597A3D6B56FF9829A5E8B85" \
                       "9E857EA95A03512E2BAE7391688D264A" \
                       "A5663B0341DB9CCFD2C4C5F421FEC814" \
                       "8001B72E848A38CAE1C65F78E56ABDEF" \
                       "E12D3C039B8A02D6BE593F0BBBDA56F1" \
                       "ECF677152EF804370C1A305CAF3B5BF1" \
                       "30879B56C61DE584A0F53A2447A51E", 16 ) );
    printf( "  MPI test #1 (mul_mpi): " );
    if( mpi_cmp_mpi( &X, &U ) != 0 )
    {
        printf( "failed\n" );
        return( 1 );
    }
    printf( "passed\n" );
    CHK( mpi_div_mpi( &X, &Y, &A, &N ) );
    CHK( mpi_read( &U, "256567336059E52CAE22925474705F39A94", 16 ) );
    CHK( mpi_read( &V, "6613F26162223DF488E9CD48CC132C7A" \
                       "0AC93C701B001B092E4E5B9F73BCD27B" \
                       "9EE50D0657C77F374E903CDFA4C642", 16 ) );
    printf( "  MPI test #2 (div_mpi): " );
    if( mpi_cmp_mpi( &X, &U ) != 0 ||
        mpi_cmp_mpi( &Y, &V ) != 0 )
    {
        printf( "failed\n" );
        return( 1 );
    }
    printf( "passed\n" );
    CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) );
    CHK( mpi_read( &U, "36E139AEA55215609D2816998ED020BB" \
                       "BD96C37890F65171D948E9BC7CBAA4D9" \
                       "325D24D6A3C12710F10A09FA08AB87", 16 ) );
    printf( "  MPI test #3 (exp_mod): " );
    if( mpi_cmp_mpi( &X, &U ) != 0 )
    {
        printf( "failed\n" );
        return( 1 );
    }
    printf( "passed\n" );
    CHK( mpi_inv_mod( &X, &A, &N ) );
    CHK( mpi_read( &U, "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \
                       "C3DBA76456363A10869622EAC2DD84EC" \
                       "C5B8A74DAC4D09E03B5E0BE779F2DF61", 16 ) );
    printf( "  MPI test #4 (inv_mod): " );
    if( mpi_cmp_mpi( &X, &U ) != 0 )
    {
        printf( "failed\n" );
        return( 1 );
    }
    printf( "passed\n" );
cleanup:
    if( ret != 0 )
        printf( "Unexpected error, return code = %d\n", ret );
    mpi_free( &V, &U, &Y, &X, &N, &E, &A, NULL );
    printf( "\n" );
    return( 0 );
}
#else
int mpi_self_test( void )
{
    return( 0 );
}
#endif
linux-bsp/asm-study/myboot/bootstrap.c
New file
@@ -0,0 +1,122 @@
/********************************************************************************************
 *        File:  bootstrap.c
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  This C code is the first stage bootloader(named bootstrap)
                 main code, test on FL2440 board.
 *   ChangeLog:  1, Release initial version on "Tue Jul 12 16:43:18 CST 2011"
 *
 *******************************************************************************************/
#include <common.h>
#include <nand.h>
int dbg_mode(struct boot_nand_t *nand);
unsigned long do_go_exec (ulong (*entry)(int, char * const []), int argc, char * const argv[]);
void print_buf(char *prompt, char *buf, int len)
{
    int i;
    printf("%s %d bytes\n", prompt, len);
    printf("------------------------------------------------------------------------------------\n");
    for(i=0; i<len; i++)
    {
        printf("0x%02x ", buf[i]);
        if(! (i+1)%32 )
            printf("\n");
    }
    printf("\n");
    printf("------------------------------------------------------------------------------------\n");
}
int bootstrap_main(void)
{
    struct boot_nand_t nand;
    char    buf[0x20000];
    ulong  test_block = 0x0;  /*0x1860000 is bad block*/
//    char *addr = (char *)TEXT_BASE;
    char *addr = (char *)0x36000000;
    serial_init();
    init_led_beep();
    printf("\bBootstrap Version 0.0.1\n");
    turn_led_on(LED0);
    if (nand_init(&nand) < 0)
    {
        printf("Nandflash init failure.\n");
        return -1;
    }
#if 0
    nand_scrub(&nand);
    nand_erase(&nand, test_block, 0x20000, SKIP_BAD_BLOCK);
    memset(buf,0x00, sizeof(buf));
    nand_read_spare(&nand, test_block, 64, buf);
    print_buf("Spare area read:", buf, 64);
    nand_read(&nand, test_block, nand.page_size, buf);
    print_buf("Whole page Write:", buf, nand.page_size);
#endif
#if 0
    /*Write spare area*/
    memset(buf,0x44,sizeof(buf));
    nand_write(&nand, test_block, nand.page_size, buf);
    nand_read(&nand, test_block, nand.page_size, buf);
    print_buf("Whole page Write:", buf, nand.page_size);
    nand_write_spare(&nand, 0x0000, 64, buf);
    nand_read_spare(&nand, test_block, 64, buf);
    print_buf("Spare area read:", buf, 64);
#endif
    dbg_mode(&nand);
    nand_read(&nand, LAUNCHER_NAND_ADDR, 1024, addr);
    do_go_exec((void *)addr, 0, NULL);
    while (1)
        ;
    return 0;
}
__attribute__((weak))
unsigned long do_go_exec (ulong (*entry)(int, char * const []), int argc, char * const argv[])
{
     printf ("## Starting application at 0x%08lX ...\n", entry);
     return entry (argc, argv);
}
int dbg_mode(struct boot_nand_t *nand)
{
    long size;
    char *addr = (char *)TEXT_BASE;
    ulong erase_size;
    dbg_print("Comes into bootstrap debug mode and Xmodem wait for receive new launcher:\n");
    beep(1);
    size = xmodem_recv(addr);
    dbg_print("\tBootstrap Receive Launcher file size: %ld bytes\n", size);
    erase_size = (size/nand->block_size + 1)*nand->block_size;
    nand_erase(nand, LAUNCHER_NAND_ADDR, erase_size, SKIP_BAD_BLOCK);
    nand_write(nand, LAUNCHER_NAND_ADDR, size, addr);
    return 0;
}
linux-bsp/asm-study/myboot/bootstrap.lds
New file
@@ -0,0 +1,32 @@
/********************************************************************************************
 *        File:  bootstrap.lds
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  This is the LD linker configure script for bootstrap
 *   ChangeLog:  1, Release initial version on "Tue Jul 12 16:43:18 CST 2011"
 *
 *******************************************************************************************/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS{
    . = ALIGN(4);
    .text   :
    {
      start.o   (.text)
      *(.text)
    }
    . = ALIGN(4);
    .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
    . = ALIGN(4);
    .rodata : { *(.rodata) }
    . = ALIGN(4);
    .data : { *(.data) }
    . = ALIGN(4);
    __bss_start = .;
    .bss : { *(.bss) }
    _end = .;
}
linux-bsp/asm-study/myboot/common.c
New file
@@ -0,0 +1,413 @@
/*
 *  linux/lib/vsprintf.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 */
/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
/*
 * Wirzenius wrote this portably, Torvalds fucked it up :-)
 */
#include <common.h>
void * memset(void * s,int c,size_t count)
{
    unsigned long *sl = (unsigned long *) s;
    unsigned long cl = 0;
    char *s8;
    int i;
    /* do it one word at a time (32 bits or 64 bits) while possible */
    if ( ((ulong)s & (sizeof(*sl) - 1)) == 0) {
        for (i = 0; i < sizeof(*sl); i++) {
            cl <<= 8;
            cl |= c & 0xff;
        }
        while (count >= sizeof(*sl)) {
            *sl++ = cl;
            count -= sizeof(*sl);
        }
    }
    /* fill 8 bits at a time */
    s8 = (char *)sl;
    while (count--)
        *s8++ = c;
    return s;
}
#ifdef CONFIG_PRINTF_DBG
size_t strnlen(const char *s, size_t count)
{
    const char *sc;
    for (sc = s; count-- && *sc != '\0'; ++sc)
        /* nothing */ ;
    return sc - s;
}
#define is_digit(c)    ((c) >= '0' && (c) <= '9')
static int skip_atoi(const char **s)
{
    int i = 0;
    while (is_digit(**s))
        i = i * 10 + *((*s)++) - '0';
    return i;
}
#define ZEROPAD    1               /* pad with zero */
#define SIGN    2               /* unsigned/signed long */
#define PLUS    4               /* show plus */
#define SPACE    8               /* space if plus */
#define LEFT    16              /* left justified */
#define SPECIAL    32              /* 0x */
#define LARGE    64              /* use 'ABCDEF' instead of 'abcdef' */
#ifdef CFG_64BIT_VSPRINTF
#define do_div(n,base) ({ \
    unsigned int __res; \
    __res = ((unsigned long long) n) % base; \
    n = ((unsigned long long) n) / base; \
    __res; \
})
#else
#define do_div(n,base) ({ \
    int __res; \
    __res = ((unsigned long) n) % base; \
    n = ((unsigned long) n) / base; \
    __res; \
})
#endif
#ifdef CFG_64BIT_VSPRINTF
static char *number(char *str, long long num, unsigned int base, int size, int precision, int type)
#else
static char *number(char *str, long num, unsigned int base, int size, int precision, int type)
#endif
{
    char c, sign, tmp[66];
    const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
    int i;
    if (type & LARGE)
        digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    if (type & LEFT)
        type &= ~ZEROPAD;
    if (base < 2 || base > 36)
        return 0;
    c = (type & ZEROPAD) ? '0' : ' ';
    sign = 0;
    if (type & SIGN)
    {
        if (num < 0)
        {
            sign = '-';
            num = -num;
            size--;
        }
        else if (type & PLUS)
        {
            sign = '+';
            size--;
        }
        else if (type & SPACE)
        {
            sign = ' ';
            size--;
        }
    }
    if (type & SPECIAL)
    {
        if (base == 16)
            size -= 2;
        else if (base == 8)
            size--;
    }
    i = 0;
    if (num == 0)
        tmp[i++] = '0';
    else
        while (num != 0)
            tmp[i++] = digits[do_div(num, base)];
    if (i > precision)
        precision = i;
    size -= precision;
    if (!(type & (ZEROPAD + LEFT)))
        while (size-- > 0)
            *str++ = ' ';
    if (sign)
        *str++ = sign;
    if (type & SPECIAL)
    {
        if (base == 8)
            *str++ = '0';
        else if (base == 16)
        {
            *str++ = '0';
            *str++ = digits[33];
        }
    }
    if (!(type & LEFT))
        while (size-- > 0)
            *str++ = c;
    while (i < precision--)
        *str++ = '0';
    while (i-- > 0)
        *str++ = tmp[i];
    while (size-- > 0)
        *str++ = ' ';
    return str;
}
/* Forward decl. needed for IP address printing stuff... */
int sprintf(char *buf, const char *fmt, ...);
int vsprintf(char *buf, const char *fmt, va_list args)
{
    int len;
#ifdef CFG_64BIT_VSPRINTF
    unsigned long long num;
#else
    unsigned long num;
#endif
    int i, base;
    char *str;
    const char *s;
    int flags;                  /* flags to number() */
    int field_width;            /* width of output field */
    int precision;              /* min. # of digits for integers; max
                                 * number of chars for from string */
    int qualifier;              /* 'h', 'l', or 'q' for integer fields */
    for (str = buf; *fmt; ++fmt)
    {
        if (*fmt != '%')
        {
            *str++ = *fmt;
            continue;
        }
        /* process flags */
        flags = 0;
      repeat:
        ++fmt;                  /* this also skips first '%' */
        switch (*fmt)
        {
          case '-':
              flags |= LEFT;
              goto repeat;
          case '+':
              flags |= PLUS;
              goto repeat;
          case ' ':
              flags |= SPACE;
              goto repeat;
          case '#':
              flags |= SPECIAL;
              goto repeat;
          case '0':
              flags |= ZEROPAD;
              goto repeat;
        }
        /* get field width */
        field_width = -1;
        if (is_digit(*fmt))
            field_width = skip_atoi(&fmt);
        else if (*fmt == '*')
        {
            ++fmt;
            /* it's the next argument */
            field_width = va_arg(args, int);
            if (field_width < 0)
            {
                field_width = -field_width;
                flags |= LEFT;
            }
        }
        /* get the precision */
        precision = -1;
        if (*fmt == '.')
        {
            ++fmt;
            if (is_digit(*fmt))
                precision = skip_atoi(&fmt);
            else if (*fmt == '*')
            {
                ++fmt;
                /* it's the next argument */
                precision = va_arg(args, int);
            }
            if (precision < 0)
                precision = 0;
        }
        /* get the conversion qualifier */
        qualifier = -1;
        if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
            *fmt == 'Z' || *fmt == 'z' || *fmt == 't' || *fmt == 'q')
        {
            qualifier = *fmt;
            if (qualifier == 'l' && *(fmt + 1) == 'l')
            {
                qualifier = 'q';
                ++fmt;
            }
            ++fmt;
        }
        /* default base */
        base = 10;
        switch (*fmt)
        {
          case 'c':
              if (!(flags & LEFT))
                  while (--field_width > 0)
                      *str++ = ' ';
              *str++ = (unsigned char)va_arg(args, int);
              while (--field_width > 0)
                  *str++ = ' ';
              continue;
          case 's':
              s = va_arg(args, char *);
              if (!s)
                  s = "<NULL>";
              len = strnlen(s, precision);
              if (!(flags & LEFT))
                  while (len < field_width--)
                      *str++ = ' ';
              for (i = 0; i < len; ++i)
                  *str++ = *s++;
              while (len < field_width--)
                  *str++ = ' ';
              continue;
          case 'p':
              if (field_width == -1)
              {
                  field_width = 2 * sizeof(void *);
                  flags |= ZEROPAD;
              }
              str = number(str,
                           (unsigned long)va_arg(args, void *), 16, field_width, precision, flags);
              continue;
          case 'n':
              if (qualifier == 'l')
              {
                  long *ip = va_arg(args, long *);
                  *ip = (str - buf);
              }
              else
              {
                  int *ip = va_arg(args, int *);
                  *ip = (str - buf);
              }
              continue;
          case '%':
              *str++ = '%';
              continue;
              /* integer number formats - set up the flags and "break" */
          case 'o':
              base = 8;
              break;
          case 'X':
              flags |= LARGE;
          case 'x':
              base = 16;
              break;
          case 'd':
          case 'i':
              flags |= SIGN;
          case 'u':
              break;
          default:
              *str++ = '%';
              if (*fmt)
                  *str++ = *fmt;
              else
                  --fmt;
              continue;
        }
#ifdef CFG_64BIT_VSPRINTF
        if (qualifier == 'q')   /* "quad" for 64 bit variables */
            num = va_arg(args, unsigned long long);
        else
#endif
        if (qualifier == 'l')
        {
            num = va_arg(args, unsigned long);
        }
        else if (qualifier == 'Z' || qualifier == 'z')
        {
            num = va_arg(args, size_t);
        }
        else if (qualifier == 't')
        {
            num = va_arg(args, ptrdiff_t);
        }
        else if (qualifier == 'h')
        {
            num = (unsigned short)va_arg(args, int);
            if (flags & SIGN)
                num = (short)num;
        }
        else if (flags & SIGN)
            num = va_arg(args, int);
        else
            num = va_arg(args, unsigned int);
        str = number(str, num, base, field_width, precision, flags);
    }
    *str = '\0';
    return str - buf;
}
void printf(const char *fmt, ...)
{
    va_list args;
    uint i;
    char printbuffer[CFG_PBSIZE];
    va_start(args, fmt);
    /* For this to work, printbuffer must be larger than
     * anything we ever want to print.
     */
    i = vsprintf(printbuffer, fmt, args);
    va_end(args);
    serial_puts(printbuffer);
}
int sprintf(char *buf, const char *fmt, ...)
{
    va_list args;
    int i;
    va_start(args, fmt);
    i = vsprintf(buf, fmt, args);
    va_end(args);
    return i;
}
#else
void printf(const char *fmt, ...)
{
}
#endif                          /*Define CONFIG_PRINTF_DBG */
linux-bsp/asm-study/myboot/crc32.c
New file
@@ -0,0 +1,218 @@
/*
 * This file is derived from crc32.c from the zlib-1.1.3 distribution
 * by Jean-loup Gailly and Mark Adler.
 */
/* crc32.c -- compute the CRC-32 of a data stream
 * Copyright (C) 1995-1998 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */
#include <common.h>
#define __cpu_to_le32(x) ((__u32)(x))
#define cpu_to_le32 __cpu_to_le32
# define le32_to_cpu(x)     (x)
#define local static
#define ZEXPORT    /* empty */
#define tole(x) cpu_to_le32(x)
#ifdef DYNAMIC_CRC_TABLE
local int crc_table_empty = 1;
local uint32_t crc_table[256];
local void make_crc_table OF((void));
/*
  Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
  Polynomials over GF(2) are represented in binary, one bit per coefficient,
  with the lowest powers in the most significant bit.  Then adding polynomials
  is just exclusive-or, and multiplying a polynomial by x is a right shift by
  one.  If we call the above polynomial p, and represent a byte as the
  polynomial q, also with the lowest power in the most significant bit (so the
  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
  where a mod b means the remainder after dividing a by b.
  This calculation is done using the shift-register method of multiplying and
  taking the remainder.  The register is initialized to zero, and for each
  incoming bit, x^32 is added mod p to the register if the bit is a one (where
  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
  x (which is shifting right by one and adding x^32 mod p if the bit shifted
  out is a one).  We start with the highest power (least significant bit) of
  q and repeat for all eight bits of q.
  The table is simply the CRC of all possible eight bit values.  This is all
  the information needed to generate CRC's on data a byte at a time for all
  combinations of CRC register values and incoming bytes.
*/
local void make_crc_table()
{
  uint32_t c;
  int n, k;
  uLong poly;        /* polynomial exclusive-or pattern */
  /* terms of polynomial defining this crc (except x^32): */
  static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
  /* make exclusive-or pattern from polynomial (0xedb88320L) */
  poly = 0L;
  for (n = 0; n < sizeof(p)/sizeof(Byte); n++)
    poly |= 1L << (31 - p[n]);
  for (n = 0; n < 256; n++)
  {
    c = (uLong)n;
    for (k = 0; k < 8; k++)
      c = c & 1 ? poly ^ (c >> 1) : c >> 1;
    crc_table[n] = tole(c);
  }
  crc_table_empty = 0;
}
#else
/* ========================================================================
 * Table of CRC-32's of all single-byte values (made by make_crc_table)
 */
local const uint32_t crc_table[256] = {
tole(0x00000000L), tole(0x77073096L), tole(0xee0e612cL), tole(0x990951baL),
tole(0x076dc419L), tole(0x706af48fL), tole(0xe963a535L), tole(0x9e6495a3L),
tole(0x0edb8832L), tole(0x79dcb8a4L), tole(0xe0d5e91eL), tole(0x97d2d988L),
tole(0x09b64c2bL), tole(0x7eb17cbdL), tole(0xe7b82d07L), tole(0x90bf1d91L),
tole(0x1db71064L), tole(0x6ab020f2L), tole(0xf3b97148L), tole(0x84be41deL),
tole(0x1adad47dL), tole(0x6ddde4ebL), tole(0xf4d4b551L), tole(0x83d385c7L),
tole(0x136c9856L), tole(0x646ba8c0L), tole(0xfd62f97aL), tole(0x8a65c9ecL),
tole(0x14015c4fL), tole(0x63066cd9L), tole(0xfa0f3d63L), tole(0x8d080df5L),
tole(0x3b6e20c8L), tole(0x4c69105eL), tole(0xd56041e4L), tole(0xa2677172L),
tole(0x3c03e4d1L), tole(0x4b04d447L), tole(0xd20d85fdL), tole(0xa50ab56bL),
tole(0x35b5a8faL), tole(0x42b2986cL), tole(0xdbbbc9d6L), tole(0xacbcf940L),
tole(0x32d86ce3L), tole(0x45df5c75L), tole(0xdcd60dcfL), tole(0xabd13d59L),
tole(0x26d930acL), tole(0x51de003aL), tole(0xc8d75180L), tole(0xbfd06116L),
tole(0x21b4f4b5L), tole(0x56b3c423L), tole(0xcfba9599L), tole(0xb8bda50fL),
tole(0x2802b89eL), tole(0x5f058808L), tole(0xc60cd9b2L), tole(0xb10be924L),
tole(0x2f6f7c87L), tole(0x58684c11L), tole(0xc1611dabL), tole(0xb6662d3dL),
tole(0x76dc4190L), tole(0x01db7106L), tole(0x98d220bcL), tole(0xefd5102aL),
tole(0x71b18589L), tole(0x06b6b51fL), tole(0x9fbfe4a5L), tole(0xe8b8d433L),
tole(0x7807c9a2L), tole(0x0f00f934L), tole(0x9609a88eL), tole(0xe10e9818L),
tole(0x7f6a0dbbL), tole(0x086d3d2dL), tole(0x91646c97L), tole(0xe6635c01L),
tole(0x6b6b51f4L), tole(0x1c6c6162L), tole(0x856530d8L), tole(0xf262004eL),
tole(0x6c0695edL), tole(0x1b01a57bL), tole(0x8208f4c1L), tole(0xf50fc457L),
tole(0x65b0d9c6L), tole(0x12b7e950L), tole(0x8bbeb8eaL), tole(0xfcb9887cL),
tole(0x62dd1ddfL), tole(0x15da2d49L), tole(0x8cd37cf3L), tole(0xfbd44c65L),
tole(0x4db26158L), tole(0x3ab551ceL), tole(0xa3bc0074L), tole(0xd4bb30e2L),
tole(0x4adfa541L), tole(0x3dd895d7L), tole(0xa4d1c46dL), tole(0xd3d6f4fbL),
tole(0x4369e96aL), tole(0x346ed9fcL), tole(0xad678846L), tole(0xda60b8d0L),
tole(0x44042d73L), tole(0x33031de5L), tole(0xaa0a4c5fL), tole(0xdd0d7cc9L),
tole(0x5005713cL), tole(0x270241aaL), tole(0xbe0b1010L), tole(0xc90c2086L),
tole(0x5768b525L), tole(0x206f85b3L), tole(0xb966d409L), tole(0xce61e49fL),
tole(0x5edef90eL), tole(0x29d9c998L), tole(0xb0d09822L), tole(0xc7d7a8b4L),
tole(0x59b33d17L), tole(0x2eb40d81L), tole(0xb7bd5c3bL), tole(0xc0ba6cadL),
tole(0xedb88320L), tole(0x9abfb3b6L), tole(0x03b6e20cL), tole(0x74b1d29aL),
tole(0xead54739L), tole(0x9dd277afL), tole(0x04db2615L), tole(0x73dc1683L),
tole(0xe3630b12L), tole(0x94643b84L), tole(0x0d6d6a3eL), tole(0x7a6a5aa8L),
tole(0xe40ecf0bL), tole(0x9309ff9dL), tole(0x0a00ae27L), tole(0x7d079eb1L),
tole(0xf00f9344L), tole(0x8708a3d2L), tole(0x1e01f268L), tole(0x6906c2feL),
tole(0xf762575dL), tole(0x806567cbL), tole(0x196c3671L), tole(0x6e6b06e7L),
tole(0xfed41b76L), tole(0x89d32be0L), tole(0x10da7a5aL), tole(0x67dd4accL),
tole(0xf9b9df6fL), tole(0x8ebeeff9L), tole(0x17b7be43L), tole(0x60b08ed5L),
tole(0xd6d6a3e8L), tole(0xa1d1937eL), tole(0x38d8c2c4L), tole(0x4fdff252L),
tole(0xd1bb67f1L), tole(0xa6bc5767L), tole(0x3fb506ddL), tole(0x48b2364bL),
tole(0xd80d2bdaL), tole(0xaf0a1b4cL), tole(0x36034af6L), tole(0x41047a60L),
tole(0xdf60efc3L), tole(0xa867df55L), tole(0x316e8eefL), tole(0x4669be79L),
tole(0xcb61b38cL), tole(0xbc66831aL), tole(0x256fd2a0L), tole(0x5268e236L),
tole(0xcc0c7795L), tole(0xbb0b4703L), tole(0x220216b9L), tole(0x5505262fL),
tole(0xc5ba3bbeL), tole(0xb2bd0b28L), tole(0x2bb45a92L), tole(0x5cb36a04L),
tole(0xc2d7ffa7L), tole(0xb5d0cf31L), tole(0x2cd99e8bL), tole(0x5bdeae1dL),
tole(0x9b64c2b0L), tole(0xec63f226L), tole(0x756aa39cL), tole(0x026d930aL),
tole(0x9c0906a9L), tole(0xeb0e363fL), tole(0x72076785L), tole(0x05005713L),
tole(0x95bf4a82L), tole(0xe2b87a14L), tole(0x7bb12baeL), tole(0x0cb61b38L),
tole(0x92d28e9bL), tole(0xe5d5be0dL), tole(0x7cdcefb7L), tole(0x0bdbdf21L),
tole(0x86d3d2d4L), tole(0xf1d4e242L), tole(0x68ddb3f8L), tole(0x1fda836eL),
tole(0x81be16cdL), tole(0xf6b9265bL), tole(0x6fb077e1L), tole(0x18b74777L),
tole(0x88085ae6L), tole(0xff0f6a70L), tole(0x66063bcaL), tole(0x11010b5cL),
tole(0x8f659effL), tole(0xf862ae69L), tole(0x616bffd3L), tole(0x166ccf45L),
tole(0xa00ae278L), tole(0xd70dd2eeL), tole(0x4e048354L), tole(0x3903b3c2L),
tole(0xa7672661L), tole(0xd06016f7L), tole(0x4969474dL), tole(0x3e6e77dbL),
tole(0xaed16a4aL), tole(0xd9d65adcL), tole(0x40df0b66L), tole(0x37d83bf0L),
tole(0xa9bcae53L), tole(0xdebb9ec5L), tole(0x47b2cf7fL), tole(0x30b5ffe9L),
tole(0xbdbdf21cL), tole(0xcabac28aL), tole(0x53b39330L), tole(0x24b4a3a6L),
tole(0xbad03605L), tole(0xcdd70693L), tole(0x54de5729L), tole(0x23d967bfL),
tole(0xb3667a2eL), tole(0xc4614ab8L), tole(0x5d681b02L), tole(0x2a6f2b94L),
tole(0xb40bbe37L), tole(0xc30c8ea1L), tole(0x5a05df1bL), tole(0x2d02ef8dL)
};
#endif
#if 0
/* =========================================================================
 * This function can be used by asm versions of crc32()
 */
const uint32_t * ZEXPORT get_crc_table()
{
#ifdef DYNAMIC_CRC_TABLE
  if (crc_table_empty) make_crc_table();
#endif
  return (const uint32_t *)crc_table;
}
#endif
/* ========================================================================= */
# if __BYTE_ORDER == __LITTLE_ENDIAN
#  define DO_CRC(x) crc = tab[(crc ^ (x)) & 255] ^ (crc >> 8)
# else
#  define DO_CRC(x) crc = tab[((crc >> 24) ^ (x)) & 255] ^ (crc << 8)
# endif
/* ========================================================================= */
/* No ones complement version. JFFS2 (and other things ?)
 * don't use ones compliment in their CRC calculations.
 */
uint32_t ZEXPORT crc32_no_comp(uint32_t crc, const uchar *buf, uint len)
{
    const uint32_t *tab = crc_table;
    const uint32_t *b =(const uint32_t *)buf;
    size_t rem_len;
#ifdef DYNAMIC_CRC_TABLE
    if (crc_table_empty)
      make_crc_table();
#endif
    crc = cpu_to_le32(crc);
    /* Align it */
    if (((long)b) & 3 && len) {
     uint8_t *p = (uint8_t *)b;
     do {
          DO_CRC(*p++);
     } while ((--len) && ((long)p)&3);
     b = (uint32_t *)p;
    }
    rem_len = len & 3;
    len = len >> 2;
    for (--b; len; --len) {
     /* load data 32 bits wide, xor data 32 bits wide. */
     crc ^= *++b; /* use pre increment for speed */
     DO_CRC(0);
     DO_CRC(0);
     DO_CRC(0);
     DO_CRC(0);
    }
    len = rem_len;
    /* And the last few bytes */
    if (len) {
     uint8_t *p = (uint8_t *)(b + 1) - 1;
     do {
          DO_CRC(*++p); /* use pre increment for speed */
     } while (--len);
    }
    return le32_to_cpu(crc);
}
#undef DO_CRC
uint32_t ZEXPORT crc32 (uint32_t crc, const uchar *p, uint len)
{
     return crc32_no_comp(crc ^ 0xffffffffL, p, len) ^ 0xffffffffL;
}
linux-bsp/asm-study/myboot/include/asm/errno.h
New file
@@ -0,0 +1,138 @@
#ifndef _ARM_ERRNO_H
#define _ARM_ERRNO_H
#define    EPERM         1          /* Operation not permitted */
#define    ENOENT         2          /* No such file or directory */
#define    ESRCH         3          /* No such process */
#define    EINTR         4          /* Interrupted system call */
#define    EIO         5              /* I/O error */
#define    ENXIO         6          /* No such device or address */
#define    E2BIG         7          /* Arg list too long */
#define    ENOEXEC         8          /* Exec format error */
#define    EBADF         9          /* Bad file number */
#define    ECHILD        10          /* No child processes */
#define    EAGAIN        11          /* Try again */
#define    ENOMEM        12          /* Out of memory */
#define    EACCES        13          /* Permission denied */
#define    EFAULT        14          /* Bad address */
#define    ENOTBLK        15          /* Block device required */
#define    EBUSY        16          /* Device or resource busy */
#define    EEXIST        17          /* File exists */
#define    EXDEV        18          /* Cross-device link */
#define    ENODEV        19          /* No such device */
#define    ENOTDIR        20          /* Not a directory */
#define    EISDIR        21          /* Is a directory */
#define    EINVAL        22          /* Invalid argument */
#define    ENFILE        23          /* File table overflow */
#define    EMFILE        24          /* Too many open files */
#define    ENOTTY        25          /* Not a typewriter */
#define    ETXTBSY        26          /* Text file busy */
#define    EFBIG        27          /* File too large */
#define    ENOSPC        28          /* No space left on device */
#define    ESPIPE        29          /* Illegal seek */
#define    EROFS        30          /* Read-only file system */
#define    EMLINK        31          /* Too many links */
#define    EPIPE        32          /* Broken pipe */
#define    EDOM        33          /* Math argument out of domain of func */
#define    ERANGE        34          /* Math result not representable */
#define    EDEADLK        35          /* Resource deadlock would occur */
#define    ENAMETOOLONG    36      /* File name too long */
#define    ENOLCK        37          /* No record locks available */
#define    ENOSYS        38          /* Function not implemented */
#define    ENOTEMPTY    39          /* Directory not empty */
#define    ELOOP        40          /* Too many symbolic links encountered */
#define    EWOULDBLOCK    EAGAIN      /* Operation would block */
#define    ENOMSG        42          /* No message of desired type */
#define    EIDRM        43          /* Identifier removed */
#define    ECHRNG        44          /* Channel number out of range */
#define    EL2NSYNC    45          /* Level 2 not synchronized */
#define    EL3HLT        46          /* Level 3 halted */
#define    EL3RST        47          /* Level 3 reset */
#define    ELNRNG        48          /* Link number out of range */
#define    EUNATCH        49          /* Protocol driver not attached */
#define    ENOCSI        50          /* No CSI structure available */
#define    EL2HLT        51          /* Level 2 halted */
#define    EBADE        52          /* Invalid exchange */
#define    EBADR        53          /* Invalid request descriptor */
#define    EXFULL        54          /* Exchange full */
#define    ENOANO        55          /* No anode */
#define    EBADRQC        56          /* Invalid request code */
#define    EBADSLT        57          /* Invalid slot */
#define    EDEADLOCK    58          /* File locking deadlock error */
#define    EBFONT        59          /* Bad font file format */
#define    ENOSTR        60          /* Device not a stream */
#define    ENODATA        61          /* No data available */
#define    ETIME        62          /* Timer expired */
#define    ENOSR        63          /* Out of streams resources */
#define    ENONET        64          /* Machine is not on the network */
#define    ENOPKG        65          /* Package not installed */
#define    EREMOTE        66          /* Object is remote */
#define    ENOLINK        67          /* Link has been severed */
#define    EADV        68          /* Advertise error */
#define    ESRMNT        69          /* Srmount error */
#define    ECOMM        70          /* Communication error on send */
#define    EPROTO        71          /* Protocol error */
#define    EMULTIHOP    72          /* Multihop attempted */
#define    EDOTDOT        73          /* RFS specific error */
#define    EBADMSG        74          /* Not a data message */
#define    EOVERFLOW    75          /* Value too large for defined data type */
#define    ENOTUNIQ    76          /* Name not unique on network */
#define    EBADFD        77          /* File descriptor in bad state */
#define    EREMCHG        78          /* Remote address changed */
#define    ELIBACC        79          /* Can not access a needed shared library */
#define    ELIBBAD        80          /* Accessing a corrupted shared library */
#define    ELIBSCN        81          /* .lib section in a.out corrupted */
#define    ELIBMAX        82          /* Attempting to link in too many shared libraries */
#define    ELIBEXEC    83          /* Cannot exec a shared library directly */
#define    EILSEQ        84          /* Illegal byte sequence */
#define    ERESTART    85          /* Interrupted system call should be restarted */
#define    ESTRPIPE    86          /* Streams pipe error */
#define    EUSERS        87          /* Too many users */
#define    ENOTSOCK    88          /* Socket operation on non-socket */
#define    EDESTADDRREQ    89      /* Destination address required */
#define    EMSGSIZE    90          /* Message too long */
#define    EPROTOTYPE    91          /* Protocol wrong type for socket */
#define    ENOPROTOOPT    92          /* Protocol not available */
#define    EPROTONOSUPPORT    93      /* Protocol not supported */
#define    ESOCKTNOSUPPORT    94      /* Socket type not supported */
#define    EOPNOTSUPP    95          /* Operation not supported on transport endpoint */
#define    EPFNOSUPPORT    96      /* Protocol family not supported */
#define    EAFNOSUPPORT    97      /* Address family not supported by protocol */
#define    EADDRINUSE    98          /* Address already in use */
#define    EADDRNOTAVAIL    99      /* Cannot assign requested address */
#define    ENETDOWN    100         /* Network is down */
#define    ENETUNREACH    101         /* Network is unreachable */
#define    ENETRESET    102         /* Network dropped connection because of reset */
#define    ECONNABORTED    103     /* Software caused connection abort */
#define    ECONNRESET    104         /* Connection reset by peer */
#define    ENOBUFS        105         /* No buffer space available */
#define    EISCONN        106         /* Transport endpoint is already connected */
#define    ENOTCONN    107         /* Transport endpoint is not connected */
#define    ESHUTDOWN    108         /* Cannot send after transport endpoint shutdown */
#define    ETOOMANYREFS    109     /* Too many references: cannot splice */
#define    ETIMEDOUT    110         /* Connection timed out */
#define    ECONNREFUSED    111     /* Connection refused */
#define    EHOSTDOWN    112         /* Host is down */
#define    EHOSTUNREACH    113     /* No route to host */
#define    EALREADY    114         /* Operation already in progress */
#define    EINPROGRESS    115         /* Operation now in progress */
#define    ESTALE        116         /* Stale NFS file handle */
#define    EUCLEAN        117         /* Structure needs cleaning */
#define    ENOTNAM        118         /* Not a XENIX named type file */
#define    ENAVAIL        119         /* No XENIX semaphores available */
#define    EISNAM        120         /* Is a named type file */
#define    EREMOTEIO    121         /* Remote I/O error */
#define    EDQUOT        122         /* Quota exceeded */
#define    ENOMEDIUM    123         /* No medium found */
#define    EMEDIUMTYPE    124         /* Wrong medium type */
/* Should never be seen by user programs */
#define ERESTARTSYS    512
#define ERESTARTNOINTR    513
#define ERESTARTNOHAND    514     /* restart if no handler.. */
#define ENOIOCTLCMD    515         /* No ioctl command */
#define _LAST_ERRNO    515
#endif
linux-bsp/asm-study/myboot/include/asm/hardware.h
New file
@@ -0,0 +1,43 @@
#ifndef _ARCH_HARDWARE_H_
#define _ARCH_HARDWARE_H_
#include <asm/sizes.h>
#ifndef __ASSEMBLY__
#define UData(Data)    ((unsigned long) (Data))
#define __REG(x)    (*(vu_long *)(x))
#define __REGl(x)    (*(vu_long *)(x))
#define __REGi(x)   (*(vu_int *)(x))
#define __REGw(x)    (*(vu_short *)(x))
#define __REGb(x)    (*(vu_char *)(x))
#define __REG2(x,y)    (*(vu_long *)((x) + (y)))
#else
#define UData(Data)    (Data)
#define __REG(x)    (x)
#define __REGl(x)    (x)
#define __REGi(x)    (x)
#define __REGw(x)    (x)
#define __REGb(x)    (x)
#define __REG2(x,y)    ((x) + (y))
#endif
#define Fld(Size, Shft)    (((Size) << 16) + (Shft))
#define FSize(Field)    ((Field) >> 16)
#define FShft(Field)    ((Field) & 0x0000FFFF)
#define FMsk(Field)    (((UData (1) << FSize (Field)) - 1) << FShft (Field))
#define FAlnMsk(Field)    ((UData (1) << FSize (Field)) - 1)
#define F1stBit(Field)    (UData (1) << FShft (Field))
#define FClrBit(Data, Bit)    (Data = (Data & ~(Bit)))
#define FClrFld(Data, Field)    (Data = (Data & ~FMsk(Field)))
#define FInsrt(Value, Field) \
                    (UData (Value) << FShft (Field))
#define FExtr(Data, Field) \
                    ((UData (Data) >> FShft (Field)) & FAlnMsk (Field))
#endif                          /* _ARCH_HARDWARE_H_ */
linux-bsp/asm-study/myboot/include/asm/io.h
New file
@@ -0,0 +1,330 @@
/*
 *  linux/include/asm-arm/io.h
 *
 *  Copyright (C) 1996-2000 Russell King
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * Modifications:
 *  16-Sep-1996    RMK    Inlined the inx/outx functions & optimised for both
 *            constant addresses and variable addresses.
 *  04-Dec-1997    RMK    Moved a lot of this stuff to the new architecture
 *            specific IO header files.
 *  27-Mar-1999    PJB    Second parameter of memcpy_toio is const..
 *  04-Apr-1999    PJB    Added check_signature.
 *  12-Dec-1999    RMK    More cleanups
 *  18-Jun-2000 RMK    Removed virt_to_* and friends definitions
 */
#ifndef __ASM_ARM_IO_H
#define __ASM_ARM_IO_H
#ifdef __KERNEL__
#include <linux/types.h>
static inline void sync(void)
{
}
/*
 * Given a physical address and a length, return a virtual address
 * that can be used to access the memory range with the caching
 * properties specified by "flags".
 */
#define MAP_NOCACHE    (0)
#define MAP_WRCOMBINE    (0)
#define MAP_WRBACK    (0)
#define MAP_WRTHROUGH    (0)
static inline void *map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
{
    return (void *)paddr;
}
/*
 * Take down a mapping set up by map_physmem().
 */
static inline void unmap_physmem(void *vaddr, unsigned long flags)
{
}
/*
 * Generic virtual read/write.  Note that we don't support half-word
 * read/writes.  We define __arch_*[bl] here, and leave __arch_*w
 * to the architecture specific code.
 */
#define __arch_getb(a)            (*(volatile unsigned char *)(a))
#define __arch_getw(a)            (*(volatile unsigned short *)(a))
#define __arch_getl(a)            (*(volatile unsigned int *)(a))
#define __arch_putb(v,a)        (*(volatile unsigned char *)(a) = (v))
#define __arch_putw(v,a)        (*(volatile unsigned short *)(a) = (v))
#define __arch_putl(v,a)        (*(volatile unsigned int *)(a) = (v))
extern void __raw_writesb(unsigned int addr, const void *data, int bytelen);
extern void __raw_writesw(unsigned int addr, const void *data, int wordlen);
extern void __raw_writesl(unsigned int addr, const void *data, int longlen);
extern void __raw_readsb(unsigned int addr, void *data, int bytelen);
extern void __raw_readsw(unsigned int addr, void *data, int wordlen);
extern void __raw_readsl(unsigned int addr, void *data, int longlen);
#define __raw_writeb(v,a)        __arch_putb(v,a)
#define __raw_writew(v,a)        __arch_putw(v,a)
#define __raw_writel(v,a)        __arch_putl(v,a)
#define __raw_readb(a)            __arch_getb(a)
#define __raw_readw(a)            __arch_getw(a)
#define __raw_readl(a)            __arch_getl(a)
#define writeb(v,a)            __arch_putb(v,a)
#define writew(v,a)            __arch_putw(v,a)
#define writel(v,a)            __arch_putl(v,a)
#define readb(a)            __arch_getb(a)
#define readw(a)            __arch_getw(a)
#define readl(a)            __arch_getl(a)
/*
 * The compiler seems to be incapable of optimising constants
 * properly.  Spell it out to the compiler in some cases.
 * These are only valid for small values of "off" (< 1<<12)
 */
#define __raw_base_writeb(val,base,off)    __arch_base_putb(val,base,off)
#define __raw_base_writew(val,base,off)    __arch_base_putw(val,base,off)
#define __raw_base_writel(val,base,off)    __arch_base_putl(val,base,off)
#define __raw_base_readb(base,off)    __arch_base_getb(base,off)
#define __raw_base_readw(base,off)    __arch_base_getw(base,off)
#define __raw_base_readl(base,off)    __arch_base_getl(base,off)
/*
 * Now, pick up the machine-defined IO definitions
 */
#if 0                           /* XXX###XXX */
#include <asm/arch/io.h>
#endif                          /* XXX###XXX */
/*
 *  IO port access primitives
 *  -------------------------
 *
 * The ARM doesn't have special IO access instructions; all IO is memory
 * mapped.  Note that these are defined to perform little endian accesses
 * only.  Their primary purpose is to access PCI and ISA peripherals.
 *
 * Note that for a big endian machine, this implies that the following
 * big endian mode connectivity is in place, as described by numerous
 * ARM documents:
 *
 *    PCI:  D0-D7   D8-D15 D16-D23 D24-D31
 *    ARM: D24-D31 D16-D23  D8-D15  D0-D7
 *
 * The machine specific io.h include defines __io to translate an "IO"
 * address to a memory address.
 *
 * Note that we prevent GCC re-ordering or caching values in expressions
 * by introducing sequence points into the in*() definitions.  Note that
 * __raw_* do not guarantee this behaviour.
 *
 * The {in,out}[bwl] macros are for emulating x86-style PCI/ISA IO space.
 */
#ifdef __io
#define outb(v,p)            __raw_writeb(v,__io(p))
#define outw(v,p)            __raw_writew(cpu_to_le16(v),__io(p))
#define outl(v,p)            __raw_writel(cpu_to_le32(v),__io(p))
#define inb(p)    ({ unsigned int __v = __raw_readb(__io(p)); __v; })
#define inw(p)    ({ unsigned int __v = le16_to_cpu(__raw_readw(__io(p))); __v; })
#define inl(p)    ({ unsigned int __v = le32_to_cpu(__raw_readl(__io(p))); __v; })
#define outsb(p,d,l)            __raw_writesb(__io(p),d,l)
#define outsw(p,d,l)            __raw_writesw(__io(p),d,l)
#define outsl(p,d,l)            __raw_writesl(__io(p),d,l)
#define insb(p,d,l)            __raw_readsb(__io(p),d,l)
#define insw(p,d,l)            __raw_readsw(__io(p),d,l)
#define insl(p,d,l)            __raw_readsl(__io(p),d,l)
#endif
#define outb_p(val,port)        outb((val),(port))
#define outw_p(val,port)        outw((val),(port))
#define outl_p(val,port)        outl((val),(port))
#define inb_p(port)            inb((port))
#define inw_p(port)            inw((port))
#define inl_p(port)            inl((port))
#define outsb_p(port,from,len)        outsb(port,from,len)
#define outsw_p(port,from,len)        outsw(port,from,len)
#define outsl_p(port,from,len)        outsl(port,from,len)
#define insb_p(port,to,len)        insb(port,to,len)
#define insw_p(port,to,len)        insw(port,to,len)
#define insl_p(port,to,len)        insl(port,to,len)
/*
 * ioremap and friends.
 *
 * ioremap takes a PCI memory address, as specified in
 * linux/Documentation/IO-mapping.txt.  If you want a
 * physical address, use __ioremap instead.
 */
extern void *__ioremap(unsigned long offset, size_t size, unsigned long flags);
extern void __iounmap(void *addr);
/*
 * Generic ioremap support.
 *
 * Define:
 *  iomem_valid_addr(off,size)
 *  iomem_to_phys(off)
 */
#ifdef iomem_valid_addr
#define __arch_ioremap(off,sz,nocache)                \
 ({                                \
    unsigned long _off = (off), _size = (sz);        \
    void *_ret = (void *)0;                    \
    if (iomem_valid_addr(_off, _size))            \
        _ret = __ioremap(iomem_to_phys(_off),_size,0);    \
    _ret;                            \
 })
#define __arch_iounmap __iounmap
#endif
#define ioremap(off,sz)            __arch_ioremap((off),(sz),0)
#define ioremap_nocache(off,sz)        __arch_ioremap((off),(sz),1)
#define iounmap(_addr)            __arch_iounmap(_addr)
/*
 * DMA-consistent mapping functions.  These allocate/free a region of
 * uncached, unwrite-buffered mapped memory space for use with DMA
 * devices.  This is the "generic" version.  The PCI specific version
 * is in pci.h
 */
extern void *consistent_alloc(int gfp, size_t size, dma_addr_t * handle);
extern void consistent_free(void *vaddr, size_t size, dma_addr_t handle);
extern void consistent_sync(void *vaddr, size_t size, int rw);
/*
 * String version of IO memory access ops:
 */
extern void _memcpy_fromio(void *, unsigned long, size_t);
extern void _memcpy_toio(unsigned long, const void *, size_t);
extern void _memset_io(unsigned long, int, size_t);
extern void __readwrite_bug(const char *fn);
/*
 * If this architecture has PCI memory IO, then define the read/write
 * macros.  These should only be used with the cookie passed from
 * ioremap.
 */
#ifdef __mem_pci
#define readb(c) ({ unsigned int __v = __raw_readb(__mem_pci(c)); __v; })
#define readw(c) ({ unsigned int __v = le16_to_cpu(__raw_readw(__mem_pci(c))); __v; })
#define readl(c) ({ unsigned int __v = le32_to_cpu(__raw_readl(__mem_pci(c))); __v; })
#define writeb(v,c)        __raw_writeb(v,__mem_pci(c))
#define writew(v,c)        __raw_writew(cpu_to_le16(v),__mem_pci(c))
#define writel(v,c)        __raw_writel(cpu_to_le32(v),__mem_pci(c))
#define memset_io(c,v,l)        _memset_io(__mem_pci(c),(v),(l))
#define memcpy_fromio(a,c,l)        _memcpy_fromio((a),__mem_pci(c),(l))
#define memcpy_toio(c,a,l)        _memcpy_toio(__mem_pci(c),(a),(l))
#define eth_io_copy_and_sum(s,c,l,b) \
                eth_copy_and_sum((s),__mem_pci(c),(l),(b))
static inline int check_signature(unsigned long io_addr, const unsigned char *signature, int length)
{
    int retval = 0;
    do
    {
        if (readb(io_addr) != *signature)
            goto out;
        io_addr++;
        signature++;
        length--;
    }
    while (length);
    retval = 1;
  out:
    return retval;
}
#elif !defined(readb)
#define readb(addr)            (__readwrite_bug("readb"),0)
#define readw(addr)            (__readwrite_bug("readw"),0)
#define readl(addr)            (__readwrite_bug("readl"),0)
#define writeb(v,addr)            __readwrite_bug("writeb")
#define writew(v,addr)            __readwrite_bug("writew")
#define writel(v,addr)            __readwrite_bug("writel")
#define eth_io_copy_and_sum(a,b,c,d)    __readwrite_bug("eth_io_copy_and_sum")
#define check_signature(io,sig,len)    (0)
#endif                          /* __mem_pci */
/*
 * If this architecture has ISA IO, then define the isa_read/isa_write
 * macros.
 */
#ifdef __mem_isa
#define isa_readb(addr)            __raw_readb(__mem_isa(addr))
#define isa_readw(addr)            __raw_readw(__mem_isa(addr))
#define isa_readl(addr)            __raw_readl(__mem_isa(addr))
#define isa_writeb(val,addr)        __raw_writeb(val,__mem_isa(addr))
#define isa_writew(val,addr)        __raw_writew(val,__mem_isa(addr))
#define isa_writel(val,addr)        __raw_writel(val,__mem_isa(addr))
#define isa_memset_io(a,b,c)        _memset_io(__mem_isa(a),(b),(c))
#define isa_memcpy_fromio(a,b,c)    _memcpy_fromio((a),__mem_isa(b),(c))
#define isa_memcpy_toio(a,b,c)        _memcpy_toio(__mem_isa((a)),(b),(c))
#define isa_eth_io_copy_and_sum(a,b,c,d) \
                eth_copy_and_sum((a),__mem_isa(b),(c),(d))
static inline int
isa_check_signature(unsigned long io_addr, const unsigned char *signature, int length)
{
    int retval = 0;
    do
    {
        if (isa_readb(io_addr) != *signature)
            goto out;
        io_addr++;
        signature++;
        length--;
    }
    while (length);
    retval = 1;
  out:
    return retval;
}
#else                           /* __mem_isa */
#define isa_readb(addr)            (__readwrite_bug("isa_readb"),0)
#define isa_readw(addr)            (__readwrite_bug("isa_readw"),0)
#define isa_readl(addr)            (__readwrite_bug("isa_readl"),0)
#define isa_writeb(val,addr)        __readwrite_bug("isa_writeb")
#define isa_writew(val,addr)        __readwrite_bug("isa_writew")
#define isa_writel(val,addr)        __readwrite_bug("isa_writel")
#define isa_memset_io(a,b,c)        __readwrite_bug("isa_memset_io")
#define isa_memcpy_fromio(a,b,c)    __readwrite_bug("isa_memcpy_fromio")
#define isa_memcpy_toio(a,b,c)        __readwrite_bug("isa_memcpy_toio")
#define isa_eth_io_copy_and_sum(a,b,c,d) \
                __readwrite_bug("isa_eth_io_copy_and_sum")
#define isa_check_signature(io,sig,len)    (0)
#endif                          /* __mem_isa */
#endif                          /* __KERNEL__ */
#endif                          /* __ASM_ARM_IO_H */
linux-bsp/asm-study/myboot/include/asm/posix_types.h
New file
@@ -0,0 +1,80 @@
/*
 *  linux/include/asm-arm/posix_types.h
 *
 *  Copyright (C) 1996-1998 Russell King.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 *  Changelog:
 *   27-06-1996    RMK    Created
 */
#ifndef __ARCH_ARM_POSIX_TYPES_H
#define __ARCH_ARM_POSIX_TYPES_H
/*
 * This file is generally used by user-level software, so you need to
 * be a little careful about namespace pollution etc.  Also, we cannot
 * assume GCC is being used.
 */
typedef unsigned short __kernel_dev_t;
typedef unsigned long __kernel_ino_t;
typedef unsigned short __kernel_mode_t;
typedef unsigned short __kernel_nlink_t;
typedef long __kernel_off_t;
typedef int __kernel_pid_t;
typedef unsigned short __kernel_ipc_pid_t;
typedef unsigned short __kernel_uid_t;
typedef unsigned short __kernel_gid_t;
typedef unsigned int __kernel_size_t;
typedef int __kernel_ssize_t;
typedef int __kernel_ptrdiff_t;
typedef long __kernel_time_t;
typedef long __kernel_suseconds_t;
typedef long __kernel_clock_t;
typedef int __kernel_daddr_t;
typedef char *__kernel_caddr_t;
typedef unsigned short __kernel_uid16_t;
typedef unsigned short __kernel_gid16_t;
typedef unsigned int __kernel_uid32_t;
typedef unsigned int __kernel_gid32_t;
typedef unsigned short __kernel_old_uid_t;
typedef unsigned short __kernel_old_gid_t;
#ifdef __GNUC__
typedef long long __kernel_loff_t;
#endif
typedef struct
{
#if defined(__KERNEL__) || defined(__USE_ALL)
    int val[2];
#else                           /* !defined(__KERNEL__) && !defined(__USE_ALL) */
    int __val[2];
#endif                          /* !defined(__KERNEL__) && !defined(__USE_ALL) */
} __kernel_fsid_t;
#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
#undef    __FD_SET
#define __FD_SET(fd, fdsetp) \
        (((fd_set *)fdsetp)->fds_bits[fd >> 5] |= (1<<(fd & 31)))
#undef    __FD_CLR
#define __FD_CLR(fd, fdsetp) \
        (((fd_set *)fdsetp)->fds_bits[fd >> 5] &= ~(1<<(fd & 31)))
#undef    __FD_ISSET
#define __FD_ISSET(fd, fdsetp) \
        ((((fd_set *)fdsetp)->fds_bits[fd >> 5] & (1<<(fd & 31))) != 0)
#undef    __FD_ZERO
#define __FD_ZERO(fdsetp) \
        (memset (fdsetp, 0, sizeof (*(fd_set *)fdsetp)))
#endif
#endif
linux-bsp/asm-study/myboot/include/asm/sizes.h
New file
@@ -0,0 +1,52 @@
/*
 * 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
 */
/* DO NOT EDIT!! - this file automatically generated
 *                 from .s file by awk -f s2h.awk
 */
/*  Size defintions
 *  Copyright (C) ARM Limited 1998. All rights reserved.
 */
#ifndef __sizes_h
#define __sizes_h                       1
/* handy sizes */
#define SZ_1K                           0x00000400
#define SZ_4K                           0x00001000
#define SZ_8K                           0x00002000
#define SZ_16K                          0x00004000
#define SZ_64K                          0x00010000
#define SZ_128K                         0x00020000
#define SZ_256K                         0x00040000
#define SZ_512K                         0x00080000
#define SZ_1M                           0x00100000
#define SZ_2M                           0x00200000
#define SZ_4M                           0x00400000
#define SZ_8M                           0x00800000
#define SZ_16M                          0x01000000
#define SZ_32M                          0x02000000
#define SZ_64M                          0x04000000
#define SZ_128M                         0x08000000
#define SZ_256M                         0x10000000
#define SZ_512M                         0x20000000
#define SZ_1G                           0x40000000
#define SZ_2G                           0x80000000
#endif
/*         END */
linux-bsp/asm-study/myboot/include/asm/types.h
New file
@@ -0,0 +1,53 @@
#ifndef __ASM_ARM_TYPES_H
#define __ASM_ARM_TYPES_H
typedef unsigned short umode_t;
/*
 * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
 * header files exported to user space
 */
typedef __signed__ char __s8;
typedef unsigned char __u8;
typedef __signed__ short __s16;
typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
#if defined(__GNUC__)
__extension__ typedef __signed__ long long __s64;
__extension__ typedef unsigned long long __u64;
#endif
/*
 * These aren't exported outside the kernel to avoid name space clashes
 */
#ifdef __KERNEL__
typedef signed char s8;
typedef unsigned char u8;
typedef signed short s16;
typedef unsigned short u16;
typedef signed int s32;
typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
#define BITS_PER_LONG 32
/* Dma addresses are 32-bits wide.  */
typedef u32 dma_addr_t;
typedef unsigned long phys_addr_t;
typedef unsigned long phys_size_t;
#endif                          /* __KERNEL__ */
#endif
linux-bsp/asm-study/myboot/include/bignum.h
New file
@@ -0,0 +1,380 @@
/**
 * \file bignum.h
 */
#ifndef _BIGNUM_H
#define _BIGNUM_H
#ifdef __cplusplus
extern "C" {
#endif
#define ERR_MPI_INVALID_CHARACTER               0x0002
#define ERR_MPI_INVALID_PARAMETER               0x0004
#define ERR_MPI_BUFFER_TOO_SMALL                0x0006
#define ERR_MPI_NEGATIVE_VALUE                  0x0008
#define ERR_MPI_DIVISION_BY_ZERO                0x000A
#define ERR_MPI_NOT_INVERTIBLE                  0x000C
#define ERR_MPI_IS_COMPOSITE                    0x000E
#define CHK(fc) if( ( ret = fc ) != 0 ) goto cleanup
/*
 * Define the base limb type
 */
#if defined(HAVE_INT16) /* 8086 */
typedef unsigned int  t_int;
typedef unsigned long t_dbl;
#else
typedef unsigned long t_int;
typedef unsigned long long t_dbl;
#endif
#define ciL    (int) sizeof(t_int)      /* chars in limb  */
#define biL    (ciL << 3)               /* bits  in limb  */
#define biH    (ciL << 2)               /* half limb size */
/**
 * \brief          MPI structure
 */
typedef struct
{
    int s;              /*!<  integer sign      */
    int n;              /*!<  total # of limbs  */
//    t_int *p;           /*!<  pointer to limbs  */
    unsigned long long *p;           /*!<  pointer to limbs  */
}
mpi;
/**
 * \brief          Initialize one or more mpi
 */
void mpi_init( mpi *X, ... );
/**
 * \brief          Unallocate one or more mpi
 */
void mpi_free( mpi *X, ... );
/**
 * \brief          Enlarge X to the specified # of limbs
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed
 */
int mpi_grow( mpi *X, int nblimbs );
/**
 * \brief          Copy the contents of Y into X
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed
 */
int mpi_copy( mpi *X, mpi *Y );
/**
 * \brief          Swap the contents of X and Y
 */
void mpi_swap( mpi *X, mpi *Y );
/**
 * \brief          Set value from integer
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed
 */
int mpi_lset( mpi *X, int z );
/**
 * \brief          Set value from string
 *
 * \param X        destination mpi
 * \param s        string to read the value from
 * \param radix    numeric base of "s"
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed,
 *                 ERR_MPI_INVALID_PARAMETER if the radix is invalid
 *                 ERR_MPI_INVALID_CHARACTER if a non-digit is found
 */
int mpi_read( mpi *X, char *s, int radix );
/**
 * \brief          Print the value of X into fout
 *
 * \param name     string printed before the value
 * \param X        mpi to be printed
 * \param radix    chosen numeric base
 * \param fout     output file stream
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed,
 *                 ERR_MPI_INVALID_PARAMETER if the radix is invalid
 */
int mpi_showf( char *name, mpi *X, int radix, FILE *fout );
/**
 * \brief          Print the value of X on the console
 *
 * \param name     string printed before the value
 * \param X        mpi to be printed
 * \param radix    chosen numeric base
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed,
 *                 ERR_MPI_INVALID_PARAMETER if the radix is invalid
 */
int mpi_show( char *name, mpi *X, int radix );
/**
 * \brief          Import an unsigned value from binary data
 *
 * \param X        destination mpi
 * \param buf      input buffer
 * \param buflen   size of buffer
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed
 */
int mpi_import( mpi *X, unsigned char *buf, int buflen );
/**
 * \brief          Export an unsigned value into binary data
 *
 * \param X        source mpi
 * \param buf      output buffer
 * \param buflen   size of buffer
 *
 * \return         0 if successful,
 *                 ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough
 *
 * \note           Call this function with *buflen = 0 to obtain the
 *                 required buffer size in *buflen.
 */
int mpi_export( mpi *X, unsigned char *buf, int *buflen );
/**
 * \brief          Return actual size in bits (without leading 0s)
 */
int mpi_size( mpi *X );
/**
 * \brief          Return number of least significant bits
 */
int mpi_lsb( mpi *X );
/**
 * \brief          Left-shift: X <<= count
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed
 */
int mpi_shift_l( mpi *X, int count );
/**
 * \brief          Right-shift: X >>= count
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed
 */
int mpi_shift_r( mpi *X, int count );
/**
 * \brief          Compare unsigned values
 *
 * \return         1 if |X| is greater than |Y|,
 *                -1 if |X| is lesser  than |Y| or
 *                 0 if |X| is equal to |Y|
 */
int mpi_cmp_abs( mpi *X, mpi *Y );
/**
 * \brief          Compare signed values
 *
 * \return         1 if X is greater than Y,
 *                -1 if X is lesser  than Y or
 *                 0 if X is equal to Y
 */
int mpi_cmp_mpi( mpi *X, mpi *Y );
/**
 * \brief          Compare signed values
 *
 * \return         1 if X is greater than z,
 *                -1 if X is lesser  than z or
 *                 0 if X is equal to z
 */
int mpi_cmp_int( mpi *X, int z );
/**
 * \brief          Unsigned addition: X = |A| + |B|
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed
 */
int mpi_add_abs( mpi *X, mpi *A, mpi *B );
/**
 * \brief          Unsigned substraction: X = |A| - |B|
 *
 * \return         0 if successful,
 *                 ERR_MPI_NEGATIVE_VALUE if B is greater than A
 */
int mpi_sub_abs( mpi *X, mpi *A, mpi *B );
/**
 * \brief          Signed addition: X = A + B
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed
 */
int mpi_add_mpi( mpi *X, mpi *A, mpi *B );
/**
 * \brief          Signed substraction: X = A - B
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed
 */
int mpi_sub_mpi( mpi *X, mpi *A, mpi *B );
/**
 * \brief          Signed addition: X = A + b
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed
 */
int mpi_add_int( mpi *X, mpi *A, int b );
/**
 * \brief          Signed substraction: X = A - b
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed
 */
int mpi_sub_int( mpi *X, mpi *A, int b );
/**
 * \brief          Baseline multiplication: X = A * B
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed
 */
int mpi_mul_mpi( mpi *X, mpi *A, mpi *B );
/**
 * \brief          Baseline multiplication: X = A * b
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed
 */
int mpi_mul_int( mpi *X, mpi *A, t_int b );
/**
 * \brief          Division by mpi: A = Q * B + R
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed,
 *                 ERR_MPI_DIVISION_BY_ZERO if B == 0
 *
 * \note           Either Q or R can be NULL.
 */
int mpi_div_mpi( mpi *Q, mpi *R, mpi *A, mpi *B );
/**
 * \brief          Division by int: A = Q * b + R
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed,
 *                 ERR_MPI_DIVISION_BY_ZERO if b == 0
 *
 * \note           Either Q or R can be NULL.
 */
int mpi_div_int( mpi *Q, mpi *R, mpi *A, int b );
/**
 * \brief          Modulo: R = A mod B
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed,
 *                 ERR_MPI_DIVISION_BY_ZERO if B == 0
 */
int mpi_mod_mpi( mpi *R, mpi *A, mpi *B );
/**
 * \brief          Modulo: r = A mod b
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed,
 *                 ERR_MPI_DIVISION_BY_ZERO if b == 0,
 */
int mpi_mod_int( t_int *r, mpi *A, int b );
/**
 * \brief          Sliding-window exponentiation: X = A^E mod N
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed,
 *                 ERR_MPI_INVALID_PARAMETER if N is negative or even
 *
 * \note           _RR is used to avoid re-computing R*R mod N across
 *                 multiple calls, which speeds up things a bit. It can
 *                 be set to NULL if the extra performance is unneeded.
 */
int mpi_exp_mod( mpi *X, mpi *A, mpi *E, mpi *N, mpi *_RR );
/**
 * \brief          Greatest common divisor: G = gcd(A, B)
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed
 */
int mpi_gcd( mpi *G, mpi *A, mpi *B );
/**
 * \brief          Modular inverse: X = A^-1 mod N
 *
 * \return         0 if successful,
 *                 1 if memory allocation failed,
 *                 ERR_MPI_INVALID_PARAMETER if N is negative or nil
 *                 ERR_MPI_NOT_INVERTIBLE if A has no inverse mod N
 */
int mpi_inv_mod( mpi *X, mpi *A, mpi *N );
/**
 * \brief          Miller-Rabin primality test
 *
 * \return         0 if successful (probably prime),
 *                 1 if memory allocation failed,
 *                 ERR_MPI_IS_COMPOSITE if X is not prime
 */
int mpi_is_prime( mpi *X );
/**
 * \brief          Prime number generation
 *
 * \param X        destination mpi
 * \param nbits    required size of X in bits
 * \param dh_flag  set this to 1 if (X-1)/2 must also be prime
 *                 (needed for Diffie-Hellman)
 * \param rng_f    points to the RNG function
 * \param rng_d    points to the RNG data
 *
 * \return         0 if successful (probably prime),
 *                 1 if memory allocation failed,
 *                 ERR_MPI_INVALID_PARAMETER if nbits is < 3
 */
int mpi_gen_prime( mpi *X, int nbits, int dh_flag,
                   int (*rng_f)(void *), void *rng_d );
/**
 * \brief          Checkup routine
 *
 * \return         0 if successful, or 1 if the test failed
 */
int mpi_self_test( void );
#ifdef __cplusplus
}
#endif
#endif /* bignum.h */
linux-bsp/asm-study/myboot/include/bn_asm.h
New file
@@ -0,0 +1,549 @@
/**
 * \file bn_asm.h
 *
 *      Multiply source vector [s] with b, add result
 *       to destination vector [d] and set carry c.
 */
#ifndef _BN_ASM_H
#define _BN_ASM_H
#if defined(__GNUC__)
#if defined(__i386__)
#define MULADDC_INIT                            \
    asm( "movl   %0, %%esi      " :: "m" (s));  \
    asm( "movl   %0, %%edi      " :: "m" (d));  \
    asm( "movl   %0, %%ecx      " :: "m" (c));  \
    asm( "movl   %0, %%ebx      " :: "m" (b));
#define MULADDC_CORE                            \
    asm( "lodsl                 " );            \
    asm( "mull   %ebx           " );            \
    asm( "addl   %ecx,   %eax   " );            \
    asm( "adcl   $0,     %edx   " );            \
    asm( "addl   (%edi), %eax   " );            \
    asm( "adcl   $0,     %edx   " );            \
    asm( "movl   %edx,   %ecx   " );            \
    asm( "stosl                 " );
#define MULADDC_STOP                            \
    asm( "movl   %%ecx, %0      " : "=m" (c));  \
    asm( "movl   %%edi, %0      " : "=m" (d));  \
    asm( "movl   %%esi, %0      " : "=m" (s) :: \
    "eax", "ecx", "edx", "ebx", "esi", "edi" );
#if defined(HAVE_SSE2)
#define MULADDC_HUIT                            \
    asm( "movd     %ecx,     %mm1     " );      \
    asm( "movd     %ebx,     %mm0     " );      \
    asm( "movd     (%edi),   %mm3     " );      \
    asm( "paddq    %mm3,     %mm1     " );      \
    asm( "movd     (%esi),   %mm2     " );      \
    asm( "pmuludq  %mm0,     %mm2     " );      \
    asm( "movd     4(%esi),  %mm4     " );      \
    asm( "pmuludq  %mm0,     %mm4     " );      \
    asm( "movd     8(%esi),  %mm6     " );      \
    asm( "pmuludq  %mm0,     %mm6     " );      \
    asm( "movd     12(%esi), %mm7     " );      \
    asm( "pmuludq  %mm0,     %mm7     " );      \
    asm( "paddq    %mm2,     %mm1     " );      \
    asm( "movd     4(%edi),  %mm3     " );      \
    asm( "paddq    %mm4,     %mm3     " );      \
    asm( "movd     8(%edi),  %mm5     " );      \
    asm( "paddq    %mm6,     %mm5     " );      \
    asm( "movd     12(%edi), %mm4     " );      \
    asm( "paddq    %mm4,     %mm7     " );      \
    asm( "movd     %mm1,     (%edi)   " );      \
    asm( "movd     16(%esi), %mm2     " );      \
    asm( "pmuludq  %mm0,     %mm2     " );      \
    asm( "psrlq    $32,      %mm1     " );      \
    asm( "movd     20(%esi), %mm4     " );      \
    asm( "pmuludq  %mm0,     %mm4     " );      \
    asm( "paddq    %mm3,     %mm1     " );      \
    asm( "movd     24(%esi), %mm6     " );      \
    asm( "pmuludq  %mm0,     %mm6     " );      \
    asm( "movd     %mm1,     4(%edi)  " );      \
    asm( "psrlq    $32,      %mm1     " );      \
    asm( "movd     28(%esi), %mm3     " );      \
    asm( "pmuludq  %mm0,     %mm3     " );      \
    asm( "paddq    %mm5,     %mm1     " );      \
    asm( "movd     16(%edi), %mm5     " );      \
    asm( "paddq    %mm5,     %mm2     " );      \
    asm( "movd     %mm1,     8(%edi)  " );      \
    asm( "psrlq    $32,      %mm1     " );      \
    asm( "paddq    %mm7,     %mm1     " );      \
    asm( "movd     20(%edi), %mm5     " );      \
    asm( "paddq    %mm5,     %mm4     " );      \
    asm( "movd     %mm1,     12(%edi) " );      \
    asm( "psrlq    $32,      %mm1     " );      \
    asm( "paddq    %mm2,     %mm1     " );      \
    asm( "movd     24(%edi), %mm5     " );      \
    asm( "paddq    %mm5,     %mm6     " );      \
    asm( "movd     %mm1,     16(%edi) " );      \
    asm( "psrlq    $32,      %mm1     " );      \
    asm( "paddq    %mm4,     %mm1     " );      \
    asm( "movd     28(%edi), %mm5     " );      \
    asm( "paddq    %mm5,     %mm3     " );      \
    asm( "movd     %mm1,     20(%edi) " );      \
    asm( "psrlq    $32,      %mm1     " );      \
    asm( "paddq    %mm6,     %mm1     " );      \
    asm( "movd     %mm1,     24(%edi) " );      \
    asm( "psrlq    $32,      %mm1     " );      \
    asm( "paddq    %mm3,     %mm1     " );      \
    asm( "movd     %mm1,     28(%edi) " );      \
    asm( "addl     $32,      %edi     " );      \
    asm( "addl     $32,      %esi     " );      \
    asm( "psrlq    $32,      %mm1     " );      \
    asm( "movd     %mm1,     %ecx     " );
#endif /* SSE2 */
#endif /* i386 */
#if defined(__amd64__) || defined (__x86_64__)
#define MULADDC_INIT                            \
    asm( "movq   %0, %%rsi      " :: "m" (s));  \
    asm( "movq   %0, %%rdi      " :: "m" (d));  \
    asm( "movq   %0, %%rcx      " :: "m" (c));  \
    asm( "movq   %0, %%rbx      " :: "m" (b));  \
    asm( "xorq   %r8, %r8       " );
#define MULADDC_CORE                            \
    asm( "movq  (%rsi),%rax     " );            \
    asm( "mulq   %rbx           " );            \
    asm( "addq   $8,   %rsi     " );            \
    asm( "addq   %rcx, %rax     " );            \
    asm( "movq   %r8,  %rcx     " );            \
    asm( "adcq   $0,   %rdx     " );            \
    asm( "nop                   " );            \
    asm( "addq   %rax, (%rdi)   " );            \
    asm( "adcq   %rdx, %rcx     " );            \
    asm( "addq   $8,   %rdi     " );
#define MULADDC_STOP                            \
    asm( "movq   %%rcx, %0      " : "=m" (c));  \
    asm( "movq   %%rdi, %0      " : "=m" (d));  \
    asm( "movq   %%rsi, %0      " : "=m" (s) :: \
    "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" );
#endif /* AMD64 */
#if defined(__mc68020__) || defined(__mcpu32__)
#define MULADDC_INIT                            \
    asm( "movl   %0, %%a2       " :: "m" (s));  \
    asm( "movl   %0, %%a3       " :: "m" (d));  \
    asm( "movl   %0, %%d3       " :: "m" (c));  \
    asm( "movl   %0, %%d2       " :: "m" (b));  \
    asm( "moveq  #0, %d0        " );
#define MULADDC_CORE                            \
    asm( "movel  %a2@+, %d1     " );            \
    asm( "mulul  %d2, %d4:%d1   " );            \
    asm( "addl   %d3, %d1       " );            \
    asm( "addxl  %d0, %d4       " );            \
    asm( "moveq  #0,  %d3       " );            \
    asm( "addl   %d1, %a3@+     " );            \
    asm( "addxl  %d4, %d3       " );
#define MULADDC_STOP                            \
    asm( "movl   %%d3, %0       " : "=m" (c));  \
    asm( "movl   %%a3, %0       " : "=m" (d));  \
    asm( "movl   %%a2, %0       " : "=m" (s) :: \
    "d0", "d1", "d2", "d3", "d4", "a2", "a3" );
#define MULADDC_HUIT                            \
    asm( "movel  %a2@+, %d1     " );            \
    asm( "mulul  %d2, %d4:%d1   " );            \
    asm( "addxl  %d3, %d1       " );            \
    asm( "addxl  %d0, %d4       " );            \
    asm( "addl   %d1, %a3@+     " );            \
    asm( "movel  %a2@+, %d1     " );            \
    asm( "mulul  %d2, %d3:%d1   " );            \
    asm( "addxl  %d4, %d1       " );            \
    asm( "addxl  %d0, %d3       " );            \
    asm( "addl   %d1, %a3@+     " );            \
    asm( "movel  %a2@+, %d1     " );            \
    asm( "mulul  %d2, %d4:%d1   " );            \
    asm( "addxl  %d3, %d1       " );            \
    asm( "addxl  %d0, %d4       " );            \
    asm( "addl   %d1, %a3@+     " );            \
    asm( "movel  %a2@+, %d1     " );            \
    asm( "mulul  %d2, %d3:%d1   " );            \
    asm( "addxl  %d4, %d1       " );            \
    asm( "addxl  %d0, %d3       " );            \
    asm( "addl   %d1, %a3@+     " );            \
    asm( "movel  %a2@+, %d1     " );            \
    asm( "mulul  %d2, %d4:%d1   " );            \
    asm( "addxl  %d3, %d1       " );            \
    asm( "addxl  %d0, %d4       " );            \
    asm( "addl   %d1, %a3@+     " );            \
    asm( "movel  %a2@+, %d1     " );            \
    asm( "mulul  %d2, %d3:%d1   " );            \
    asm( "addxl  %d4, %d1       " );            \
    asm( "addxl  %d0, %d3       " );            \
    asm( "addl   %d1, %a3@+     " );            \
    asm( "movel  %a2@+, %d1     " );            \
    asm( "mulul  %d2, %d4:%d1   " );            \
    asm( "addxl  %d3, %d1       " );            \
    asm( "addxl  %d0, %d4       " );            \
    asm( "addl   %d1, %a3@+     " );            \
    asm( "movel  %a2@+, %d1     " );            \
    asm( "mulul  %d2, %d3:%d1   " );            \
    asm( "addxl  %d4, %d1       " );            \
    asm( "addxl  %d0, %d3       " );            \
    asm( "addl   %d1, %a3@+     " );            \
    asm( "addxl  %d0, %d3       " );
#endif /* MC68020 */
#if defined(__powerpc__)   || defined(__ppc__)
#if defined(__powerpc64__) || defined(__ppc64__)
#define MULADDC_INIT                            \
    asm( "ld     %%r3, %0       " :: "m" (s));  \
    asm( "ld     %%r4, %0       " :: "m" (d));  \
    asm( "ld     %%r5, %0       " :: "m" (c));  \
    asm( "ld     %%r6, %0       " :: "m" (b));  \
    asm( "addi   %r3, %r3, -8   " );            \
    asm( "addi   %r4, %r4, -8   " );            \
    asm( "addic  %r5, %r5,  0   " );
#define MULADDC_CORE                            \
    asm( "ldu    %r7, 8(%r3)    " );            \
    asm( "mulld  %r8, %r7, %r6  " );            \
    asm( "mulhdu %r9, %r7, %r6  " );            \
    asm( "adde   %r8, %r8, %r5  " );            \
    asm( "ld     %r7, 8(%r4)    " );            \
    asm( "addze  %r5, %r9       " );            \
    asm( "addc   %r8, %r8, %r7  " );            \
    asm( "stdu   %r8, 8(%r4)    " );
#define MULADDC_STOP                            \
    asm( "addze  %r5, %r5       " );            \
    asm( "addi   %r4, %r4, 8    " );            \
    asm( "addi   %r3, %r3, 8    " );            \
    asm( "std    %%r5, %0       " : "=m" (c));  \
    asm( "std    %%r4, %0       " : "=m" (d));  \
    asm( "std    %%r3, %0       " : "=m" (s) :: \
    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
#else
#define MULADDC_INIT                            \
    asm( "lwz    %%r3, %0       " :: "m" (s));  \
    asm( "lwz    %%r4, %0       " :: "m" (d));  \
    asm( "lwz    %%r5, %0       " :: "m" (c));  \
    asm( "lwz    %%r6, %0       " :: "m" (b));  \
    asm( "addi   %r3, %r3, -4   " );            \
    asm( "addi   %r4, %r4, -4   " );            \
    asm( "addic  %r5, %r5,  0   " );
#define MULADDC_CORE                            \
    asm( "lwzu   %r7, 4(%r3)    " );            \
    asm( "mullw  %r8, %r7, %r6  " );            \
    asm( "mulhwu %r9, %r7, %r6  " );            \
    asm( "adde   %r8, %r8, %r5  " );            \
    asm( "lwz    %r7, 4(%r4)    " );            \
    asm( "addze  %r5, %r9       " );            \
    asm( "addc   %r8, %r8, %r7  " );            \
    asm( "stwu   %r8, 4(%r4)    " );
#define MULADDC_STOP                            \
    asm( "addze  %r5, %r5       " );            \
    asm( "addi   %r4, %r4, 4    " );            \
    asm( "addi   %r3, %r3, 4    " );            \
    asm( "stw    %%r5, %0       " : "=m" (c));  \
    asm( "stw    %%r4, %0       " : "=m" (d));  \
    asm( "stw    %%r3, %0       " : "=m" (s) :: \
    "r3", "r4", "r5", "r6", "r7", "r8", "r9" );
#endif /* PowerPC 32-bit */
#endif /* PowerPC 64-bit */
#if defined(__sparc__)
#define MULADDC_INIT                            \
    asm( "ld     %0, %%o0       " :: "m" (s));  \
    asm( "ld     %0, %%o1       " :: "m" (d));  \
    asm( "ld     %0, %%o2       " :: "m" (c));  \
    asm( "ld     %0, %%o3       " :: "m" (b));
#define MULADDC_CORE                            \
    asm( "ld    [%o0], %o4      " );            \
    asm( "inc      4,  %o0      " );            \
    asm( "ld    [%o1], %o5      " );            \
    asm( "umul   %o3,  %o4, %o4 " );            \
    asm( "addcc  %o4,  %o2, %o4 " );            \
    asm( "rd      %y,  %g1      " );            \
    asm( "addx   %g1,    0, %g1 " );            \
    asm( "addcc  %o4,  %o5, %o4 " );            \
    asm( "st     %o4, [%o1]     " );            \
    asm( "addx   %g1,    0, %o2 " );            \
    asm( "inc      4,  %o1      " );
#define MULADDC_STOP                            \
    asm( "st     %%o2, %0       " : "=m" (c));  \
    asm( "st     %%o1, %0       " : "=m" (d));  \
    asm( "st     %%o0, %0       " : "=m" (s) :: \
    "g1", "o0", "o1", "o2", "o3", "o4", "o5" );
#endif /* SPARC8 */
#if defined(__tricore__)
#define MULADDC_INIT                            \
    asm( "ld.a   %%a2, %0       " :: "m" (s));  \
    asm( "ld.a   %%a3, %0       " :: "m" (d));  \
    asm( "ld.w   %%d4, %0       " :: "m" (c));  \
    asm( "ld.w   %%d1, %0       " :: "m" (b));  \
    asm( "xor    %d5, %d5       " );
#define MULADDC_CORE                            \
    asm( "ld.w   %d0,   [%a2+]      " );        \
    asm( "madd.u %e2, %e4, %d0, %d1 " );        \
    asm( "ld.w   %d0,   [%a3]       " );        \
    asm( "addx   %d2,    %d2,  %d0  " );        \
    asm( "addc   %d3,    %d3,    0  " );        \
    asm( "mov    %d4,    %d3        " );        \
    asm( "st.w  [%a3+],  %d2        " );
#define MULADDC_STOP                            \
    asm( "st.w   %0, %%d4       " : "=m" (c));  \
    asm( "st.a   %0, %%a3       " : "=m" (d));  \
    asm( "st.a   %0, %%a2       " : "=m" (s) :: \
    "d0", "d1", "e2", "d4", "a2", "a3" );
#endif /* TriCore */
#if defined(__arm__)
#define MULADDC_INIT                            \
    asm( "ldr    r0, %0         " :: "m" (s));  \
    asm( "ldr    r1, %0         " :: "m" (d));  \
    asm( "ldr    r2, %0         " :: "m" (c));  \
    asm( "ldr    r3, %0         " :: "m" (b));
#define MULADDC_CORE                            \
    asm( "ldr    r4, [r0], #4   " );            \
    asm( "mov    r5, #0         " );            \
    asm( "ldr    r6, [r1]       " );            \
    asm( "umlal  r2, r5, r3, r4 " );            \
    asm( "adds   r7, r6, r2     " );            \
    asm( "adc    r2, r5, #0     " );            \
    asm( "str    r7, [r1], #4   " );
#define MULADDC_STOP                            \
    asm( "str    r2, %0         " : "=m" (c));  \
    asm( "str    r1, %0         " : "=m" (d));  \
    asm( "str    r0, %0         " : "=m" (s) :: \
    "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7" );
#endif /* ARMv3 */
#if defined(__alpha__)
#define MULADDC_INIT                            \
    asm( "ldq    $1, %0         " :: "m" (s));  \
    asm( "ldq    $2, %0         " :: "m" (d));  \
    asm( "ldq    $3, %0         " :: "m" (c));  \
    asm( "ldq    $4, %0         " :: "m" (b));
#define MULADDC_CORE                            \
    asm( "ldq    $6,  0($1)     " );            \
    asm( "addq   $1,  8, $1     " );            \
    asm( "mulq   $6, $4, $7     " );            \
    asm( "umulh  $6, $4, $6     " );            \
    asm( "addq   $7, $3, $7     " );            \
    asm( "cmpult $7, $3, $3     " );            \
    asm( "ldq    $5,  0($2)     " );            \
    asm( "addq   $7, $5, $7     " );            \
    asm( "cmpult $7, $5, $5     " );            \
    asm( "stq    $7,  0($2)     " );            \
    asm( "addq   $2,  8, $2     " );            \
    asm( "addq   $6, $3, $3     " );            \
    asm( "addq   $5, $3, $3     " );
#define MULADDC_STOP                            \
    asm( "stq    $3, %0         " : "=m" (c));  \
    asm( "stq    $2, %0         " : "=m" (d));  \
    asm( "stq    $1, %0         " : "=m" (s) :: \
    "$1", "$2", "$3", "$4", "$5", "$6", "$7" );
#endif /* Alpha */
#if defined(__mips__)
#define MULADDC_INIT                            \
    asm( "lw     $10, %0        " :: "m" (s));  \
    asm( "lw     $11, %0        " :: "m" (d));  \
    asm( "lw     $12, %0        " :: "m" (c));  \
    asm( "lw     $13, %0        " :: "m" (b));
#define MULADDC_CORE                            \
    asm( "lw     $14, 0($10)    " );            \
    asm( "multu  $13, $14       " );            \
    asm( "addi   $10, $10, 4    " );            \
    asm( "mflo   $14            " );            \
    asm( "mfhi   $9             " );            \
    asm( "addu   $14, $12, $14  " );            \
    asm( "lw     $15, 0($11)    " );            \
    asm( "sltu   $12, $14, $12  " );            \
    asm( "addu   $15, $14, $15  " );            \
    asm( "sltu   $14, $15, $14  " );            \
    asm( "addu   $12, $12, $9   " );            \
    asm( "sw     $15, 0($11)    " );            \
    asm( "addu   $12, $12, $14  " );            \
    asm( "addi   $11, $11, 4    " );
#define MULADDC_STOP                            \
    asm( "sw     $12, %0        " : "=m" (c));  \
    asm( "sw     $11, %0        " : "=m" (d));  \
    asm( "sw     $10, %0        " : "=m" (s) :: \
    "$9", "$10", "$11", "$12", "$13", "$14", "$15" );
#endif /* MIPS */
#endif /* GNUC */
#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__)
#define MULADDC_INIT                            \
    __asm   mov     esi, s                      \
    __asm   mov     edi, d                      \
    __asm   mov     ecx, c                      \
    __asm   mov     ebx, b
#define MULADDC_CORE                            \
    __asm   lodsd                               \
    __asm   mul     ebx                         \
    __asm   add     eax, ecx                    \
    __asm   adc     edx, 0                      \
    __asm   add     eax, [edi]                  \
    __asm   adc     edx, 0                      \
    __asm   mov     ecx, edx                    \
    __asm   stosd
#define MULADDC_STOP                            \
    __asm   mov     c, ecx                      \
    __asm   mov     d, edi                      \
    __asm   mov     s, esi                      \
#if defined HAVE_SSE2
#define EMIT __asm _emit
#define MULADDC_HUIT                            \
    EMIT 0x0F  EMIT 0x6E  EMIT 0xC9             \
    EMIT 0x0F  EMIT 0x6E  EMIT 0xC3             \
    EMIT 0x0F  EMIT 0x6E  EMIT 0x1F             \
    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
    EMIT 0x0F  EMIT 0x6E  EMIT 0x16             \
    EMIT 0x0F  EMIT 0xF4  EMIT 0xD0             \
    EMIT 0x0F  EMIT 0x6E  EMIT 0x66  EMIT 0x04  \
    EMIT 0x0F  EMIT 0xF4  EMIT 0xE0             \
    EMIT 0x0F  EMIT 0x6E  EMIT 0x76  EMIT 0x08  \
    EMIT 0x0F  EMIT 0xF4  EMIT 0xF0             \
    EMIT 0x0F  EMIT 0x6E  EMIT 0x7E  EMIT 0x0C  \
    EMIT 0x0F  EMIT 0xF4  EMIT 0xF8             \
    EMIT 0x0F  EMIT 0xD4  EMIT 0xCA             \
    EMIT 0x0F  EMIT 0x6E  EMIT 0x5F  EMIT 0x04  \
    EMIT 0x0F  EMIT 0xD4  EMIT 0xDC             \
    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x08  \
    EMIT 0x0F  EMIT 0xD4  EMIT 0xEE             \
    EMIT 0x0F  EMIT 0x6E  EMIT 0x67  EMIT 0x0C  \
    EMIT 0x0F  EMIT 0xD4  EMIT 0xFC             \
    EMIT 0x0F  EMIT 0x7E  EMIT 0x0F             \
    EMIT 0x0F  EMIT 0x6E  EMIT 0x56  EMIT 0x10  \
    EMIT 0x0F  EMIT 0xF4  EMIT 0xD0             \
    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
    EMIT 0x0F  EMIT 0x6E  EMIT 0x66  EMIT 0x14  \
    EMIT 0x0F  EMIT 0xF4  EMIT 0xE0             \
    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
    EMIT 0x0F  EMIT 0x6E  EMIT 0x76  EMIT 0x18  \
    EMIT 0x0F  EMIT 0xF4  EMIT 0xF0             \
    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x04  \
    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
    EMIT 0x0F  EMIT 0x6E  EMIT 0x5E  EMIT 0x1C  \
    EMIT 0x0F  EMIT 0xF4  EMIT 0xD8             \
    EMIT 0x0F  EMIT 0xD4  EMIT 0xCD             \
    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x10  \
    EMIT 0x0F  EMIT 0xD4  EMIT 0xD5             \
    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x08  \
    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
    EMIT 0x0F  EMIT 0xD4  EMIT 0xCF             \
    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x14  \
    EMIT 0x0F  EMIT 0xD4  EMIT 0xE5             \
    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x0C  \
    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
    EMIT 0x0F  EMIT 0xD4  EMIT 0xCA             \
    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x18  \
    EMIT 0x0F  EMIT 0xD4  EMIT 0xF5             \
    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x10  \
    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
    EMIT 0x0F  EMIT 0xD4  EMIT 0xCC             \
    EMIT 0x0F  EMIT 0x6E  EMIT 0x6F  EMIT 0x1C  \
    EMIT 0x0F  EMIT 0xD4  EMIT 0xDD             \
    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x14  \
    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
    EMIT 0x0F  EMIT 0xD4  EMIT 0xCE             \
    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x18  \
    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
    EMIT 0x0F  EMIT 0xD4  EMIT 0xCB             \
    EMIT 0x0F  EMIT 0x7E  EMIT 0x4F  EMIT 0x1C  \
    EMIT 0x83  EMIT 0xC7  EMIT 0x20             \
    EMIT 0x83  EMIT 0xC6  EMIT 0x20             \
    EMIT 0x0F  EMIT 0x73  EMIT 0xD1  EMIT 0x20  \
    EMIT 0x0F  EMIT 0x7E  EMIT 0xC9
#endif /* SSE2 */
#endif /* MSVC */
#if !defined(MULADDC_CORE)
#if defined(HAVE_LONGLONG)
#define MULADDC_INIT                    \
{                                       \
    t_dbl r;                            \
    t_int r0, r1;
#define MULADDC_CORE                    \
    r   = *(s++) * (t_dbl) b;           \
    r0  = r;                            \
    r1  = r >> biL;                     \
    r0 += c;  r1 += (r0 <  c);          \
    r0 += *d; r1 += (r0 < *d);          \
    c = r1; *(d++) = r0;
#define MULADDC_STOP                    \
}
#else
#define MULADDC_INIT                    \
{                                       \
    t_int s0, s1, b0, b1;               \
    t_int r0, r1, rx, ry;               \
    b0 = ( b << biH ) >> biH;           \
    b1 = ( b >> biH );
#define MULADDC_CORE                    \
    s0 = ( *s << biH ) >> biH;          \
    s1 = ( *s >> biH ); s++;            \
    rx = s0 * b1; r0 = s0 * b0;         \
    ry = s1 * b0; r1 = s1 * b1;         \
    r1 += ( rx >> biH );                \
    r1 += ( ry >> biH );                \
    rx <<= biH; ry <<= biH;             \
    r0 += rx; r1 += (r0 < rx);          \
    r0 += ry; r1 += (r0 < ry);          \
    r0 +=  c; r1 += (r0 <  c);          \
    r0 += *d; r1 += (r0 < *d);          \
    c = r1; *(d++) = r0;
#define MULADDC_STOP                    \
}
#endif /* C (generic)  */
#endif /* C (longlong) */
#endif /* bn_asm.h */
linux-bsp/asm-study/myboot/include/common.h
New file
@@ -0,0 +1,52 @@
/********************************************************************************************
 *        File:  common.h
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  A busy head file
 *   ChangeLog:  1, Release initial version on "Tue Jul 12 16:43:18 CST 2011"
 *
 *******************************************************************************************/
#ifndef __COMMON_H
#define __COMMON_H
#include <stdarg.h>
#include <config.h>
#include <asm/types.h>
#include <asm/io.h>
#include <linux/types.h>
#define DEBUG
#ifdef DEBUG
#define dbg_print(format,args...) printf(format, ##args)
#else
#define dbg_print(format,args...) do{} while(0);
#endif
typedef unsigned char uchar;
typedef volatile unsigned long vu_long;
typedef volatile unsigned short vu_short;
typedef volatile unsigned char vu_char;
typedef volatile unsigned int vu_int;
/*Define in board.c*/
inline void delay(unsigned long loops);
void init_led_beep(void);
void turn_led_on(int led);
void turn_led_off(int led);
void beep(int count);
void serial_init(void);
void serial_send_byte(char c);
int serial_is_recv_enable(void);
int serial_recv_byte(void);
void serial_puts(const char *s);
long xmodem_recv(char *buf);
/*Define in printf.c*/
void * memset(void * s,int c,size_t count);
void printf(const char *fmt, ...);
int sprintf(char *buf, const char *fmt, ...);
#endif
linux-bsp/asm-study/myboot/include/config.h
New file
@@ -0,0 +1,36 @@
/********************************************************************************************
 *        File:  start.S - Startup Code for ARM920 CPU-core
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  Configure file for bootstrap, just like u-boot-1.3.4/include/config/s3c2440.h
 *   ChangeLog:  1, Release initial version on "Tue Jul 12 16:43:18 CST 2011"
 *
 *******************************************************************************************/
#ifndef __CONFIG_H
#define __CONFIG_H
#ifdef BOARD_SMDK2440
#include <s3c2440.h>
#define CONFIG_S3C2440
#endif
#define MDIV_405                    0x7f << 12
#define PSDIV_405                   0x21
#define CONFIG_LED_DEBUG            1
#define CONFIG_SYS_MALLOC_LEN       (1024*1024)
#define CONFIG_SYS_GBL_DATA_SIZE    128
#define CONFIG_STACKSIZE            0x40000
#define CFG_PBSIZE                  384 /* Print Buffer Size */
#define CFG_MAX_NAND_DEVICE         1
#define NAND_MAX_CHIPS              1
#define CFG_NAND_BASE               0x4E000000
#define BOOTLOADER_ENV_ADDR       0x20000   /*Bootloader enviroment start address*/
#define LAUNCHER_NAND_ADDR        0x40000   /*Laucher save in Nandflash address*/
#endif
linux-bsp/asm-study/myboot/include/linux/bitops.h
New file
@@ -0,0 +1,75 @@
#ifndef _LINUX_BITOPS_H
#define _LINUX_BITOPS_H
/*
 * ffs: find first bit set. This is defined the same way as
 * the libc and compiler builtin ffs routines, therefore
 * differs in spirit from the above ffz (man ffs).
 */
static inline int generic_ffs(int x)
{
    int r = 1;
    if (!x)
        return 0;
    if (!(x & 0xffff))
    {
        x >>= 16;
        r += 16;
    }
    if (!(x & 0xff))
    {
        x >>= 8;
        r += 8;
    }
    if (!(x & 0xf))
    {
        x >>= 4;
        r += 4;
    }
    if (!(x & 3))
    {
        x >>= 2;
        r += 2;
    }
    if (!(x & 1))
    {
        x >>= 1;
        r += 1;
    }
    return r;
}
/*
 * hweightN: returns the hamming weight (i.e. the number
 * of bits set) of a N-bit word
 */
static inline unsigned int generic_hweight32(unsigned int w)
{
    unsigned int res = (w & 0x55555555) + ((w >> 1) & 0x55555555);
    res = (res & 0x33333333) + ((res >> 2) & 0x33333333);
    res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F);
    res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF);
    return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF);
}
static inline unsigned int generic_hweight16(unsigned int w)
{
    unsigned int res = (w & 0x5555) + ((w >> 1) & 0x5555);
    res = (res & 0x3333) + ((res >> 2) & 0x3333);
    res = (res & 0x0F0F) + ((res >> 4) & 0x0F0F);
    return (res & 0x00FF) + ((res >> 8) & 0x00FF);
}
static inline unsigned int generic_hweight8(unsigned int w)
{
    unsigned int res = (w & 0x55) + ((w >> 1) & 0x55);
    res = (res & 0x33) + ((res >> 2) & 0x33);
    return (res & 0x0F) + ((res >> 4) & 0x0F);
}
//#include <asm/bitops.h>
#endif
linux-bsp/asm-study/myboot/include/linux/config.h
New file
@@ -0,0 +1,6 @@
#ifndef _LINUX_CONFIG_H
#define _LINUX_CONFIG_H
/* #include <linux/autoconf.h> */
#endif
linux-bsp/asm-study/myboot/include/linux/ctype.h
New file
@@ -0,0 +1,54 @@
#ifndef _LINUX_CTYPE_H
#define _LINUX_CTYPE_H
/*
 * NOTE! This ctype does not handle EOF like the standard C
 * library is required to.
 */
#define _U    0x01                /* upper */
#define _L    0x02                /* lower */
#define _D    0x04                /* digit */
#define _C    0x08                /* cntrl */
#define _P    0x10                /* punct */
#define _S    0x20                /* white space (space/lf/tab) */
#define _X    0x40                /* hex digit */
#define _SP    0x80                /* hard space (0x20) */
extern unsigned char _ctype[];
#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
#define isalnum(c)    ((__ismask(c)&(_U|_L|_D)) != 0)
#define isalpha(c)    ((__ismask(c)&(_U|_L)) != 0)
#define iscntrl(c)    ((__ismask(c)&(_C)) != 0)
#define isdigit(c)    ((__ismask(c)&(_D)) != 0)
#define isgraph(c)    ((__ismask(c)&(_P|_U|_L|_D)) != 0)
#define islower(c)    ((__ismask(c)&(_L)) != 0)
#define isprint(c)    ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
#define ispunct(c)    ((__ismask(c)&(_P)) != 0)
#define isspace(c)    ((__ismask(c)&(_S)) != 0)
#define isupper(c)    ((__ismask(c)&(_U)) != 0)
#define isxdigit(c)    ((__ismask(c)&(_D|_X)) != 0)
#define isascii(c) (((unsigned char)(c))<=0x7f)
#define toascii(c) (((unsigned char)(c))&0x7f)
static inline unsigned char __tolower(unsigned char c)
{
    if (isupper(c))
        c -= 'A' - 'a';
    return c;
}
static inline unsigned char __toupper(unsigned char c)
{
    if (islower(c))
        c -= 'a' - 'A';
    return c;
}
#define tolower(c) __tolower(c)
#define toupper(c) __toupper(c)
#endif
linux-bsp/asm-study/myboot/include/linux/posix_types.h
New file
@@ -0,0 +1,49 @@
#ifndef _LINUX_POSIX_TYPES_H
#define _LINUX_POSIX_TYPES_H
#include <linux/stddef.h>
/*
 * This allows for 1024 file descriptors: if NR_OPEN is ever grown
 * beyond that you'll have to change this too. But 1024 fd's seem to be
 * enough even for such "real" unices like OSF/1, so hopefully this is
 * one limit that doesn't have to be changed [again].
 *
 * Note that POSIX wants the FD_CLEAR(fd,fdsetp) defines to be in
 * <sys/time.h> (and thus <linux/time.h>) - but this is a more logical
 * place for them. Solved by having dummy defines in <sys/time.h>.
 */
/*
 * Those macros may have been defined in <gnu/types.h>. But we always
 * use the ones here.
 */
#undef __NFDBITS
#define __NFDBITS    (8 * sizeof(unsigned long))
#undef __FD_SETSIZE
#define __FD_SETSIZE    1024
#undef __FDSET_LONGS
#define __FDSET_LONGS    (__FD_SETSIZE/__NFDBITS)
#undef __FDELT
#define    __FDELT(d)    ((d) / __NFDBITS)
#undef __FDMASK
#define    __FDMASK(d)    (1UL << ((d) % __NFDBITS))
typedef struct
{
    unsigned long fds_bits[__FDSET_LONGS];
} __kernel_fd_set;
/* Type of a signal handler.  */
typedef void (*__kernel_sighandler_t) (int);
/* Type of a SYSV IPC key.  */
typedef int __kernel_key_t;
#include <asm/posix_types.h>
#endif                          /* _LINUX_POSIX_TYPES_H */
linux-bsp/asm-study/myboot/include/linux/stddef.h
New file
@@ -0,0 +1,18 @@
#ifndef _LINUX_STDDEF_H
#define _LINUX_STDDEF_H
#undef NULL
#if defined(__cplusplus)
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#ifndef _SIZE_T
#include <linux/types.h>
#endif
#undef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
linux-bsp/asm-study/myboot/include/linux/string.h
New file
@@ -0,0 +1,89 @@
#ifndef _LINUX_STRING_H_
#define _LINUX_STRING_H_
#include <linux/types.h>        /* for size_t */
#include <linux/stddef.h>       /* for NULL */
#ifdef __cplusplus
extern "C"
{
#endif
    extern char *___strtok;
    extern char *strpbrk(const char *, const char *);
    extern char *strtok(char *, const char *);
    extern char *strsep(char **, const char *);
    extern __kernel_size_t strspn(const char *, const char *);
/*
 * Include machine specific inline routines
 */
#include <asm/string.h>
#ifndef __HAVE_ARCH_STRCPY
    extern char *strcpy(char *, const char *);
#endif
#ifndef __HAVE_ARCH_STRNCPY
    extern char *strncpy(char *, const char *, __kernel_size_t);
#endif
#ifndef __HAVE_ARCH_STRCAT
    extern char *strcat(char *, const char *);
#endif
#ifndef __HAVE_ARCH_STRNCAT
    extern char *strncat(char *, const char *, __kernel_size_t);
#endif
#ifndef __HAVE_ARCH_STRCMP
    extern int strcmp(const char *, const char *);
#endif
#ifndef __HAVE_ARCH_STRNCMP
    extern int strncmp(const char *, const char *, __kernel_size_t);
#endif
#if 0                           /* not used - was: #ifndef __HAVE_ARCH_STRNICMP */
    extern int strnicmp(const char *, const char *, __kernel_size_t);
#endif
#ifndef __HAVE_ARCH_STRCHR
    extern char *strchr(const char *, int);
#endif
#ifndef __HAVE_ARCH_STRRCHR
    extern char *strrchr(const char *, int);
#endif
#ifndef __HAVE_ARCH_STRSTR
    extern char *strstr(const char *, const char *);
#endif
#ifndef __HAVE_ARCH_STRLEN
    extern __kernel_size_t strlen(const char *);
#endif
#ifndef __HAVE_ARCH_STRNLEN
    extern __kernel_size_t strnlen(const char *, __kernel_size_t);
#endif
#ifndef __HAVE_ARCH_STRDUP
    extern char *strdup(const char *);
#endif
#ifndef __HAVE_ARCH_STRSWAB
    extern char *strswab(const char *);
#endif
#ifndef __HAVE_ARCH_MEMSET
    extern void *memset(void *, int, __kernel_size_t);
#endif
#ifndef __HAVE_ARCH_MEMCPY
    extern void *memcpy(void *, const void *, __kernel_size_t);
#endif
#ifndef __HAVE_ARCH_MEMMOVE
    extern void *memmove(void *, const void *, __kernel_size_t);
#endif
#ifndef __HAVE_ARCH_MEMSCAN
    extern void *memscan(void *, int, __kernel_size_t);
#endif
#ifndef __HAVE_ARCH_MEMCMP
    extern int memcmp(const void *, const void *, __kernel_size_t);
#endif
#ifndef __HAVE_ARCH_MEMCHR
    extern void *memchr(const void *, int, __kernel_size_t);
#endif
#ifdef __cplusplus
}
#endif
#endif                          /* _LINUX_STRING_H_ */
linux-bsp/asm-study/myboot/include/linux/time.h
New file
@@ -0,0 +1,149 @@
#ifndef _LINUX_TIME_H
#define _LINUX_TIME_H
#include <linux/types.h>
#define _DEFUN(a,b,c) a(c)
#define _CONST const
#define _AND ,
#define _REENT_ONLY
#define SECSPERMIN    60L
#define MINSPERHOUR    60L
#define HOURSPERDAY    24L
#define SECSPERHOUR    (SECSPERMIN * MINSPERHOUR)
#define SECSPERDAY    (SECSPERHOUR * HOURSPERDAY)
#define DAYSPERWEEK    7
#define MONSPERYEAR    12
#define YEAR_BASE    1900
#define EPOCH_YEAR      1970
#define EPOCH_WDAY      4
#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
/* Used by other time functions.  */
struct tm
{
    int tm_sec;                 /* Seconds.     [0-60] (1 leap second) */
    int tm_min;                 /* Minutes.     [0-59] */
    int tm_hour;                /* Hours.       [0-23] */
    int tm_mday;                /* Day.         [1-31] */
    int tm_mon;                 /* Month.       [0-11] */
    int tm_year;                /* Year - 1900.  */
    int tm_wday;                /* Day of week. [0-6] */
    int tm_yday;                /* Days in year.[0-365] */
    int tm_isdst;               /* DST.         [-1/0/1] */
# ifdef __USE_BSD
    long int tm_gmtoff;         /* Seconds east of UTC.  */
    __const char *tm_zone;      /* Timezone abbreviation.  */
# else
    long int __tm_gmtoff;       /* Seconds east of UTC.  */
    __const char *__tm_zone;    /* Timezone abbreviation.  */
# endif
};
static inline char *_DEFUN(asctime_r, (tim_p, result), _CONST struct tm *tim_p _AND char *result)
{
    static _CONST char day_name[7][3] = {
        "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
    };
    static _CONST char mon_name[12][3] = {
        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    };
    sprintf(result, "%.3s %.3s %.2d %.2d:%.2d:%.2d %d\n",
            day_name[tim_p->tm_wday],
            mon_name[tim_p->tm_mon],
            tim_p->tm_mday, tim_p->tm_hour, tim_p->tm_min, tim_p->tm_sec, 1900 + tim_p->tm_year);
    return result;
}
static inline struct tm *_DEFUN(localtime_r, (tim_p, res),
                                _CONST time_t * tim_p _AND struct tm *res)
{
    static _CONST int mon_lengths[2][MONSPERYEAR] = {
        {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
        {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
    };
    static _CONST int year_lengths[2] = {
        365,
        366
    };
    long days, rem;
    int y;
    int yleap;
    _CONST int *ip;
    days = ((long)*tim_p) / SECSPERDAY;
    rem = ((long)*tim_p) % SECSPERDAY;
    while (rem < 0)
    {
        rem += SECSPERDAY;
        --days;
    }
    while (rem >= SECSPERDAY)
    {
        rem -= SECSPERDAY;
        ++days;
    }
    /* compute hour, min, and sec */
    res->tm_hour = (int)(rem / SECSPERHOUR);
    rem %= SECSPERHOUR;
    res->tm_min = (int)(rem / SECSPERMIN);
    res->tm_sec = (int)(rem % SECSPERMIN);
    /* compute day of week */
    if ((res->tm_wday = ((EPOCH_WDAY + days) % DAYSPERWEEK)) < 0)
        res->tm_wday += DAYSPERWEEK;
    /* compute year & day of year */
    y = EPOCH_YEAR;
    if (days >= 0)
    {
        for (;;)
        {
            yleap = isleap(y);
            if (days < year_lengths[yleap])
                break;
            y++;
            days -= year_lengths[yleap];
        }
    }
    else
    {
        do
        {
            --y;
            yleap = isleap(y);
            days += year_lengths[yleap];
        }
        while (days < 0);
    }
    res->tm_year = y - YEAR_BASE;
    res->tm_yday = days;
    ip = mon_lengths[yleap];
    for (res->tm_mon = 0; days >= ip[res->tm_mon]; ++res->tm_mon)
        days -= ip[res->tm_mon];
    res->tm_mday = days + 1;
    /* set daylight saving time flag */
    res->tm_isdst = -1;
    return (res);
}
static inline char *_DEFUN(ctime_r, (tim_p, result), _CONST time_t * tim_p _AND char *result)
{
    struct tm tm;
    return asctime_r(localtime_r(tim_p, &tm), result);
}
#endif
linux-bsp/asm-study/myboot/include/linux/types.h
New file
@@ -0,0 +1,131 @@
#ifndef _LINUX_TYPES_H
#define _LINUX_TYPES_H
#ifdef    __KERNEL__
#include <linux/config.h>
#endif
#include <linux/posix_types.h>
#include <asm/types.h>
#ifndef __KERNEL_STRICT_NAMES
typedef __kernel_fd_set fd_set;
typedef __kernel_dev_t dev_t;
typedef __kernel_ino_t ino_t;
typedef __kernel_mode_t mode_t;
typedef __kernel_nlink_t nlink_t;
typedef __kernel_off_t off_t;
typedef __kernel_pid_t pid_t;
typedef __kernel_daddr_t daddr_t;
typedef __kernel_key_t key_t;
typedef __kernel_suseconds_t suseconds_t;
#ifdef __KERNEL__
typedef __kernel_uid32_t uid_t;
typedef __kernel_gid32_t gid_t;
typedef __kernel_uid16_t uid16_t;
typedef __kernel_gid16_t gid16_t;
#ifdef CONFIG_UID16
/* This is defined by include/asm-{arch}/posix_types.h */
typedef __kernel_old_uid_t old_uid_t;
typedef __kernel_old_gid_t old_gid_t;
#endif                          /* CONFIG_UID16 */
/* libc5 includes this file to define uid_t, thus uid_t can never change
 * when it is included by non-kernel code
 */
#else
typedef __kernel_uid_t uid_t;
typedef __kernel_gid_t gid_t;
#endif                          /* __KERNEL__ */
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
typedef __kernel_loff_t loff_t;
#endif
/*
 * The following typedefs are also protected by individual ifdefs for
 * historical reasons:
 */
#ifndef _SIZE_T
#define _SIZE_T
typedef __kernel_size_t size_t;
#endif
#ifndef _SSIZE_T
#define _SSIZE_T
typedef __kernel_ssize_t ssize_t;
#endif
#ifndef _PTRDIFF_T
#define _PTRDIFF_T
typedef __kernel_ptrdiff_t ptrdiff_t;
#endif
#ifndef _TIME_T
#define _TIME_T
typedef __kernel_time_t time_t;
#endif
#ifndef _CLOCK_T
#define _CLOCK_T
typedef __kernel_clock_t clock_t;
#endif
#ifndef _CADDR_T
#define _CADDR_T
typedef __kernel_caddr_t caddr_t;
#endif
/* bsd */
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned int u_int;
typedef unsigned long u_long;
/* sysv */
typedef unsigned char unchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
#ifndef __BIT_TYPES_DEFINED__
#define __BIT_TYPES_DEFINED__
typedef __u8 u_int8_t;
typedef __s8 int8_t;
typedef __u16 u_int16_t;
typedef __s16 int16_t;
typedef __u32 u_int32_t;
typedef __s32 int32_t;
#endif                          /* !(__BIT_TYPES_DEFINED__) */
typedef __u8 uint8_t;
typedef __u16 uint16_t;
typedef __u32 uint32_t;
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
typedef __u64 uint64_t;
typedef __u64 u_int64_t;
typedef __s64 int64_t;
#endif
#endif                          /* __KERNEL_STRICT_NAMES */
/*
 * Below are truly Linux-specific types that should never collide with
 * any application/library that wants linux/types.h.
 */
struct ustat
{
    __kernel_daddr_t f_tfree;
    __kernel_ino_t f_tinode;
    char f_fname[6];
    char f_fpack[6];
};
#endif                          /* _LINUX_TYPES_H */
linux-bsp/asm-study/myboot/include/nand.h
New file
@@ -0,0 +1,271 @@
/*
 *  linux/include/linux/mtd/nand.h
 *
 *  Copyright (c) 2000 David Woodhouse <dwmw2@infradead.org>
 *                     Steven J. Hill <sjhill@realitydiluted.com>
 *               Thomas Gleixner <tglx@linutronix.de>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * Info:
 *    Contains standard defines and IDs for NAND flash devices
 *
 * Changelog:
 *    See git changelog.
 */
#ifndef __LINUX_MTD_NAND_H
#define __LINUX_MTD_NAND_H
#include <common.h>
#include <linux/bitops.h>
#define NAND_K9F2G08      0xecda
/* This constant declares the max. oobsize / page, which
 * is supported now. If you add a chip with bigger oobsize/page
 * adjust this accordingly.
 */
#define NAND_MAX_OOBSIZE    218
#define NAND_MAX_PAGESIZE    4096
/*
 * Constants for hardware specific CLE/ALE/NCE function
 *
 * These are bits which can be or'ed to set/clear multiple
 * bits in one go.
 */
/* Select the chip by setting nCE to low */
#define NAND_NCE        0x01
/* Select the command latch by setting CLE to high */
#define NAND_CLE        0x02
/* Select the address latch by setting ALE to high */
#define NAND_ALE        0x04
#define NAND_CTRL_CLE        (NAND_NCE | NAND_CLE)
#define NAND_CTRL_ALE        (NAND_NCE | NAND_ALE)
#define NAND_CTRL_CHANGE    0x80
/*
 * Standard NAND flash commands
 */
#define NAND_CMD_READ0        0x00        /*Page read period 1*/
#define NAND_CMD_READSTART    0x30        /*Page read period 2, for large page*/
#define NAND_CMD_READID        0x90        /*Read production ID*/
#define NAND_CMD_SEQIN        0x80        /*Page write period 1*/
#define NAND_CMD_PAGEPROG    0x10        /*Page write period 2*/
#define NAND_CMD_ERASE1        0x60        /*Block erase period 1*/
#define NAND_CMD_ERASE2        0xd0        /*Block erase period 2*/
#define NAND_CMD_STATUS        0x70        /*Read status command*/
#define NAND_CMD_RESET        0xff        /*Nandflash reset command*/
#define NAND_CMD_READ1        1
#define NAND_CMD_RNDOUT        0x05        /*Page random read period 1*/
#define NAND_CMD_RNDOUTSTART    0xE0    /*Page random read period 2*/
#define NAND_CMD_RNDIN        0x85        /*Page random write*/
#define NAND_CMD_READOOB    0x50
#define NAND_CMD_STATUS_MULTI    0x71
/* Extended commands for large page devices */
#define NAND_CMD_CACHEDPROG    0x15
/* Extended commands for AG-AND device */
/*
 * Note: the command for NAND_CMD_DEPLETE1 is really 0x00 but
 *       there is no way to distinguish that from NAND_CMD_READ0
 *       until the remaining sequence of commands has been completed
 *       so add a high order bit and mask it off in the command.
 */
#define NAND_CMD_DEPLETE1    0x100
#define NAND_CMD_DEPLETE2    0x38
#define NAND_CMD_STATUS_MULTI    0x71
#define NAND_CMD_STATUS_ERROR    0x72
/* multi-bank error status (banks 0-3) */
#define NAND_CMD_STATUS_ERROR0    0x73
#define NAND_CMD_STATUS_ERROR1    0x74
#define NAND_CMD_STATUS_ERROR2    0x75
#define NAND_CMD_STATUS_ERROR3    0x76
#define NAND_CMD_STATUS_RESET    0x7f
#define NAND_CMD_STATUS_CLEAR    0xff
#define NAND_CMD_NONE        -1
/* Status bits */
#define NAND_STATUS_FAIL    0x01
#define NAND_STATUS_FAIL_N1    0x02
#define NAND_STATUS_TRUE_READY    0x20
#define NAND_STATUS_READY    0x40
#define NAND_STATUS_WP        0x80
/*
 * Constants for ECC_MODES
 */
typedef enum
{
    NAND_ECC_NONE,
    NAND_ECC_SOFT,
    NAND_ECC_HW,
    NAND_ECC_HW_SYNDROME,
    NAND_ECC_HW_OOB_FIRST,
} nand_ecc_modes_t;
/*
 * Constants for Hardware ECC
 */
/* Reset Hardware ECC for read */
#define NAND_ECC_READ        0
/* Reset Hardware ECC for write */
#define NAND_ECC_WRITE        1
/* Enable Hardware ECC before syndrom is read back from flash */
#define NAND_ECC_READSYN    2
/* Bit mask for flags passed to do_nand_read_ecc */
#define NAND_GET_DEVICE        0x80
/* Option constants for bizarre disfunctionality and real
*  features
*/
/* Chip can not auto increment pages */
#define NAND_NO_AUTOINCR    0x00000001
/* Buswitdh is 16 bit */
#define NAND_BUSWIDTH_16    0x00000002
/* Device supports partial programming without padding */
#define NAND_NO_PADDING        0x00000004
/* Chip has cache program function */
#define NAND_CACHEPRG        0x00000008
/* Chip has copy back function */
#define NAND_COPYBACK        0x00000010
/* AND Chip which has 4 banks and a confusing page / block
 * assignment. See Renesas datasheet for further information */
#define NAND_IS_AND        0x00000020
/* Chip has a array of 4 pages which can be read without
 * additional ready /busy waits */
#define NAND_4PAGE_ARRAY    0x00000040
/* Chip requires that BBT is periodically rewritten to prevent
 * bits from adjacent blocks from 'leaking' in altering data.
 * This happens with the Renesas AG-AND chips, possibly others.  */
#define BBT_AUTO_REFRESH    0x00000080
/* Chip does not require ready check on read. True
 * for all large page devices, as they do not support
 * autoincrement.*/
#define NAND_NO_READRDY        0x00000100
/* Chip does not allow subpage writes */
#define NAND_NO_SUBPAGE_WRITE    0x00000200
/* Options valid for Samsung large page devices */
#define NAND_SAMSUNG_LP_OPTIONS \
    (NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK)
/* Macros to identify the above */
#define NAND_CANAUTOINCR(chip) (!(chip->options & NAND_NO_AUTOINCR))
#define NAND_MUST_PAD(chip) (!(chip->options & NAND_NO_PADDING))
#define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG))
#define NAND_HAS_COPYBACK(chip) ((chip->options & NAND_COPYBACK))
/* Large page NAND with SOFT_ECC should support subpage reads */
#define NAND_SUBPAGE_READ(chip) ((chip->ecc.mode == NAND_ECC_SOFT) \
                    && (chip->page_shift > 9))
/* Mask to zero out the chip options, which come from the id table */
#define NAND_CHIPOPTIONS_MSK    (0x0000ffff & ~NAND_NO_AUTOINCR)
/* Non chip related options */
/* Use a flash based bad block table. This option is passed to the
 * default bad block table function. */
#define NAND_USE_FLASH_BBT    0x00010000
/* This option skips the bbt scan during initialization. */
#define NAND_SKIP_BBTSCAN    0x00020000
/* This option is defined if the board driver allocates its own buffers
   (e.g. because it needs them DMA-coherent */
#define NAND_OWN_BUFFERS    0x00040000
/* Options set by nand scan */
/* bbt has already been read */
#define NAND_BBT_SCANNED    0x40000000
/* Nand scan has allocated controller struct */
#define NAND_CONTROLLER_ALLOC    0x80000000
/* Cell info constants */
#define NAND_CI_CHIPNR_MSK    0x03
#define NAND_CI_CELLTYPE_MSK    0x0C
/*
 * NAND Flash Manufacturer ID Codes
 */
#define NAND_MFR_TOSHIBA    0x98
#define NAND_MFR_SAMSUNG    0xec
#define NAND_MFR_FUJITSU    0x04
#define NAND_MFR_NATIONAL    0x8f
#define NAND_MFR_RENESAS    0x07
#define NAND_MFR_STMICRO    0x20
#define NAND_MFR_HYNIX        0xad
#define NAND_MFR_MICRON        0x2c
#define NAND_MFR_AMD        0x01
/*
* Constants for oob configuration
*/
#define NAND_SMALL_BADBLOCK_POS        5
#define NAND_LARGE_BADBLOCK_POS        0
#if defined(CONFIG_S3C2410)
#define REG_NFCONF      __REGi(ELFIN_NAND_BASE + 0x0)
#define REG_NFCMD       __REGb(ELFIN_NAND_BASE + 0x4)
#define REG_NFADDR      __REGb(ELFIN_NAND_BASE + 0x8)
#define REG_NFDATA      __REGb(ELFIN_NAND_BASE + 0xc)
#define REG_NFSTAT      __REGb(ELFIN_NAND_BASE + 0x10)
#define NFSTAT_BUSY 1
#define nand_select()   (REG_NFCONF &= ~0x800)   /*Clear bit 11*/
#define nand_deselect() (REG_NFCONF |= 0x800)
#define nand_clear_RnB()    do {} while (0)
#define nand_detect_RnB()    do {} while (0)
#define nand_wait_RnB()    do {} while (0)
#elif defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
#define REG_NFCONF      __REGi(ELFIN_NAND_BASE + 0x0)
#define REG_NFCONT      __REGi(ELFIN_NAND_BASE + 0x4)
#define REG_NFCMD       __REGb(ELFIN_NAND_BASE + 0x8)
#define REG_NFADDR      __REGb(ELFIN_NAND_BASE + 0xc)
#define REG_NFDATA      __REGb(ELFIN_NAND_BASE + 0x10)
#define REG_NFDATA16    __REGw(ELFIN_NAND_BASE + 0x10)
#define REG_NFSTAT      __REGb(ELFIN_NAND_BASE + 0x20)
#define NFSTAT_BUSY 1
#define nand_select()   (REG_NFCONT &= ~(1 << 1))
#define nand_deselect() (REG_NFCONT |= (1 << 1))
#define nand_clear_RnB()    (REG_NFSTAT |= (1 << 2))
#define nand_detect_RnB()   {while(!(REG_NFSTAT&(1<<2)));}   /*Wait Read & Busy signal goto high(not busy)*/
#define nand_wait_RnB()   {while(!(REG_NFSTAT&(1<<0)));}   /*Wait nand flash not busy, wait bit[0] goes to 1*/
#endif
#define SKIP_BAD_BLOCK       1
#define NOT_SKIP_BAD_BLOCK   0
struct boot_nand_t
{
    int page_size;
    int spare_size;
    int block_size;
    int block_num;
    int bad_block_offset;
    int id;
    //  unsigned long size;
};
int nand_init(struct boot_nand_t *nand);
int nand_read_page(struct boot_nand_t *nand, ulong page_num, ulong offset, char *data, ulong size);
int nand_write_page(struct boot_nand_t *nand, ulong page_num, ulong offset, char *data, ulong size);
int is_bad_block(struct boot_nand_t *nand, ulong addr);
int mark_bad_block(struct boot_nand_t *nand, ulong addr);
int nand_erase_block(struct boot_nand_t *nand, ulong block_num);
int nand_erase(struct boot_nand_t *nand, ulong start_addr, ulong size, int skip_bad);
void nand_scrub(struct boot_nand_t *nand);
int nand_read_spare(struct boot_nand_t *nand, ulong page_addr, int size, char *buf);
int nand_write_spare(struct boot_nand_t *nand, ulong page_addr, int size, char *buf);
int nand_read(struct boot_nand_t *nand, ulong start_addr, ulong size, char *buf);
int nand_write(struct boot_nand_t *nand, ulong start_addr, ulong size, char *buf);
#endif                          /* __LINUX_MTD_NAND_H */
linux-bsp/asm-study/myboot/include/rsa.h
New file
@@ -0,0 +1,208 @@
/**
 * \file rsa.h
 */
#ifndef _RSA_H
#define _RSA_H
#ifdef __cplusplus
extern "C" {
#endif
#include "bignum.h"
#define ERR_RSA_BAD_INPUT_DATA                  0x0300
#define ERR_RSA_INVALID_PADDING                 0x0310
#define ERR_RSA_KEY_GEN_FAILED                  0x0320
#define ERR_RSA_KEY_CHK_FAILED                  0x0330
#define ERR_RSA_PUBLIC_FAILED                   0x0340
#define ERR_RSA_PRIVATE_FAILED                  0x0350
#define ERR_RSA_VERIFY_FAILED                   0x0360
/*
 * PKCS#1 stuff
 */
#define RSA_RAW             0
#define RSA_MD2             2
#define RSA_MD4             3
#define RSA_MD5             4
#define RSA_SHA1            5
#define RSA_SIGN            0x01
#define RSA_CRYPT           0x02
/*
 * DigestInfo ::= SEQUENCE {
 *   digestAlgorithm DigestAlgorithmIdentifier,
 *   digest Digest }
 *
 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
 *
 * Digest ::= OCTET STRING
 */
#define ASN1_HASH_MDX                       \
    "\x30\x20\x30\x0C\x06\x08\x2A\x86\x48"  \
    "\x86\xF7\x0D\x02\x00\x05\x00\x04\x10"
#define ASN1_HASH_SHA1                      \
    "\x30\x21\x30\x09\x06\x05\x2B\x0E\x03"  \
    "\x02\x1A\x05\x00\x04\x14"
typedef struct
{
    int ver;    /*!<  should be 0       */
    int len;    /*!<  size(N) in chars  */
    mpi N;      /*!<  public modulus    */
    mpi E;      /*!<  public exponent   */
    mpi D;      /*!<  private exponent  */
    mpi P;      /*!<  1st prime factor  */
    mpi Q;      /*!<  2nd prime factor  */
    mpi DP;     /*!<  D mod (P - 1)     */
    mpi DQ;     /*!<  D mod (Q - 1)     */
    mpi QP;     /*!<  inverse of Q % P  */
    mpi RN;     /*!<  cached R^2 mod N  */
    mpi RP;     /*!<  cached R^2 mod P  */
    mpi RQ;     /*!<  cached R^2 mod Q  */
}
rsa_context;
/**
 * \brief          Generate an RSA keypair
 *
 * \param ctx      RSA context to be initialized
 * \param nbits    size of the public key in bits
 * \param exponent public exponent (e.g., 65537)
 * \param rng_f    points to the RNG function
 * \param rng_d    points to the RNG data
 *
 * \return         0 if successful, or an ERR_RSA_XXX error code
 */
int rsa_gen_key( rsa_context *ctx, int nbits, int exponent,
                 int (*rng_f)(void *), void *rng_d );
/**
 * \brief          Perform an RSA public key operation
 *
 * \return         0 if successful, or an ERR_RSA_XXX error code
 *
 * \note           This function does not take care of message
 *                 padding: both ilen and olen must be equal to
 *                 the modulus size (ctx->len). Also, be sure
 *                 to set input[0] = 0.
 */
int rsa_public( rsa_context   *ctx,
                unsigned char *input,  int ilen,
                unsigned char *output, int *olen );
/**
 * \brief          Perform an RSA private key operation
 *
 * \return         0 if successful, or an ERR_RSA_XXX error code
 *
 * \note           This function does not take care of message
 *                 padding: both ilen and olen must be equal to
 *                 the modulus size (ctx->len). Also, be sure
 *                 to set input[0] = 0.
 */
int rsa_private( rsa_context   *ctx,
                 unsigned char *input,  int ilen,
                 unsigned char *output, int *olen );
/**
 * \brief          Return 0 if the public key is valid,
 *                 or ERR_RSA_KEY_CHECK_FAILED
 */
int rsa_check_pubkey( rsa_context *ctx );
/**
 * \brief          Return 0 if the private key is valid,
 *                 or ERR_RSA_KEY_CHECK_FAILED
 */
int rsa_check_privkey( rsa_context *ctx );
/**
 * \brief          Add the PKCS#1 v1.5 padding and do a public RSA
 *
 * \param ctx      RSA context
 * \param input    buffer holding the data to be encrypted
 * \param ilen     length of the plaintext; cannot be longer
 *                 than the modulus, minus 3+8 for padding
 * \param output   buffer that will hold the ciphertext
 * \param olen     must be the same as the modulus size
 *                 (for example, 128 if RSA-1024 is used)
 *
 * \return         0 if successful, or an ERR_RSA_XXX error code
 */
int rsa_pkcs1_encrypt( rsa_context   *ctx,
                       unsigned char *input,  int ilen,
                       unsigned char *output, int *olen );
/**
 * \brief          Do a private RSA, removes the PKCS#1 v1.5 padding
 *
 * \param ctx      RSA context
 * \param input    buffer holding the encrypted data
 * \param ilen     must be the same as the modulus size
 * \param output   buffer that will hold the plaintext
 * \param olen     size of output buffer, will be updated
 *                 to contain the length of the plaintext
 *
 * \return         0 if successful, or an ERR_RSA_XXX error code
 */
int rsa_pkcs1_decrypt( rsa_context   *ctx,
                       unsigned char *input,  int  ilen,
                       unsigned char *output, int *olen );
/**
 * \brief          Perform a private RSA to sign a message digest
 *
 * \param ctx      RSA context
 * \param alg_id   RSA_RAW, RSA_MD2/4/5 or RSA_SHA1
 * \param hash     buffer holding the message digest
 * \param hashlen  message digest length
 * \param sig      buffer that will hold the ciphertext
 * \param siglen   must be the same as the modulus size
 *                 (for example, 128 if RSA-1024 is used)
 *
 * \return         0 if the signing operation was successful,
 *                 or an ERR_RSA_XXX error code
 */
int rsa_pkcs1_sign( rsa_context   *ctx,  int alg_id,
                    unsigned char *hash, int hashlen,
                    unsigned char *sig,  int siglen );
/**
 * \brief          Perform a public RSA and check the message digest
 *
 * \param ctx      points to an RSA public key
 * \param alg_id   RSA_RAW, RSA_MD2/4/5 or RSA_SHA1
 * \param hash     buffer holding the message digest
 * \param hashlen  message digest length
 * \param sig      buffer holding the ciphertext
 * \param siglen   must be the same as the modulus size
 *
 * \return         0 if the verify operation was successful,
 *                 or an ERR_RSA_XXX error code
 */
int rsa_pkcs1_verify( rsa_context   *ctx,  int alg_id,
                      unsigned char *hash, int hashlen,
                      unsigned char *sig,  int siglen );
/**
 * \brief          Free the components of an RSA key
 */
void rsa_free( rsa_context *ctx );
/**
 * \brief          Checkup routine
 *
 * \return         0 if successful, or 1 if the test failed
 */
int rsa_self_test( void );
#ifdef __cplusplus
}
#endif
#endif
linux-bsp/asm-study/myboot/include/s3c2440.h
New file
@@ -0,0 +1,674 @@
/*
 * (C) Copyright 2003
 * David Müller ELSOFT AG Switzerland. d.mueller@elsoft.ch
 *
 * 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
 */
/************************************************
 * NAME        : s3c2440.h
 *
 * Based on S3C2440A User's manual Rev 1.1
 ************************************************/
#ifndef __S3C2440_H__
#define __S3C2440_H__
/*This is debug on FL2440 board*/
#define BEEP     0              /*Buzzer use GPB0 */
#define LED0     5              /*LED0 use GPB5 */
#define LED1     6              /*LED1 use GPB6 */
#define LED2     8              /*LED2 use GPB8 */
#define LED3     10             /*LED3 use GPB10 */
/*FL2440 LED & Beep define end*/
#define S3C24X0_UART_CHANNELS    3
#define S3C24X0_SPI_CHANNELS    2
#include <asm/hardware.h>
#ifndef __ASSEMBLY__
typedef enum
{
    S3C24X0_UART0,
    S3C24X0_UART1,
} S3C24X0_UARTS_NR;
#include <s3c24x0.h>
#endif
#define ROM_BASE0        0x00000000  /* base address of rom bank 0 */
#define ROM_BASE1        0x04000000  /* base address of rom bank 1 */
#define DRAM_BASE0        0x30000000  /* base address of dram bank 0 */
#define DRAM_BASE1        0x00000000  /* base address of dram bank 1 */
/* S3C2440 only supports 512 Byte HW ECC */
#define S3C2410_ECCSIZE        512
#define S3C2410_ECCBYTES    3
/* S3C2440 device base addresses */
#define ELFIN_DMA_BASE        0x4b000000
#define ELFIN_USB_DEVICE_BASE    0x44a00000
#define ELFIN_I2C_BASE        0x54000000
#define ELFIN_I2S_BASE        0x55000000
#define ELFIN_ADC_BASE        0x58000000
#define ELFIN_SPI_BASE        0x59000000
#define ELFIN_SDI_BASE        0x5A000000
/*
 * Memory controller
 */
#define ELFIN_MEM_CON_BASE    0x48000000
#define BWSCON_OFFSET        0x00
#define BANKCON0_OFFSET        0x04
#define BANKCON1_OFFSET        0x08
#define BANKCON2_OFFSET        0x0c
#define BANKCON3_OFFSET        0x10
#define BANKCON4_OFFSET        0x14
#define BANKCON5_OFFSET        0x18
#define BANKCON6_OFFSET        0x1c
#define BANKCON7_OFFSET        0x20
#define REFRESH_OFFSET        0x24
#define BANKSIZE_OFFSET        0x28
#define MRSRB6_OFFSET        0x2c
#define MRSRB7_OFFSET        0x30
#define BWSCON_REG        __REG(0x48000000)
#define BANKCON0_REG        __REG(0x48000004)
#define BANKCON1_REG        __REG(0x48000008)
#define BANKCON2_REG        __REG(0x4800000c)
#define BANKCON3_REG        __REG(0x48000010)
#define BANKCON4_REG        __REG(0x48000014)
#define BANKCON5_REG        __REG(0x48000018)
#define BANKCON6_REG        __REG(0x4800001c)
#define BANKCON7_REG        __REG(0x48000020)
#define REFRESH_REG        __REG(0x48000024)
#define BANKSIZE_REG        __REG(0x48000028)
#define MRSRB6_REG        __REG(0x4800002c)
#define MRSRB7_REG        __REG(0x48000030)
/*
 * USB Host Controller
 */
#define ELFIN_USB_HOST_BASE    0x49000000
#define HcRevision_OFFSET    0x00
#define HcControl_OFFSET    0x04
#define HcCommonStatus_OFFSET    0x08
#define HcIntStatus_OFFSET    0x0c
#define HcIntEnable_OFFSET    0x10
#define HcIntDisable_OFFSET    0x14
#define HcHCCA_OFFSET        0x18
#define HcPerdCurED_OFFSET    0x1c
#define HcCtrlHeadED_OFFSET    0x20
#define HcCtrlCurED_OFFSET    0x24
#define HcBulkHeadED_OFFSET    0x28
#define HcBulkCurED_OFFSET    0x2c
#define HcDoneHead_OFFSET    0x30
#define HcRmInterval_OFFSET    0x34
#define HcFmRemain_OFFSET    0x38
#define HcFmNumber_OFFSET    0x3c
#define HcPerdStart_OFFSET    0x40
#define HcLSThres_OFFSET    0x44
#define HcRhDescA_OFFSET    0x48
#define HcRhDescB_OFFSET    0x4c
#define HcRhStatus_OFFSET    0x50
#define HcRhPortSts1_OFFSET    0x54
#define HcRhPortSts2_OFFSET    0x58
#define HcRevision_REG        __REG(0x49000000)
#define HcControl_REG        __REG(0x49000004)
#define HcCommonStatus_REG    __REG(0x49000008)
#define HcIntStatus_REG        __REG(0x4900000c)
#define HcIntEnable_REG        __REG(0x49000010)
#define HcIntDisable_REG    __REG(0x49000014)
#define HcHCCA_REG        __REG(0x49000018)
#define HcPerdCurED_REG        __REG(0x4900001c)
#define HcCtrlHeadED_REG    __REG(0x49000020)
#define HcCtrlCurED_REG        __REG(0x49000024)
#define HcBulkHeadED_REG    __REG(0x49000028)
#define HcBulkCurED_REG        __REG(0x4900002c)
#define HcDoneHead_REG        __REG(0x49000030)
#define HcRmInterval_REG    __REG(0x49000034)
#define HcFmRemain_REG        __REG(0x49000038)
#define HcFmNumber_REG        __REG(0x4900003c)
#define HcPerdStart_REG        __REG(0x49000040)
#define HcLSThres_REG        __REG(0x49000044)
#define HcRhDescA_REG        __REG(0x49000048)
#define HcRhDescB_REG        __REG(0x4900004c)
#define HcRhStatus_REG        __REG(0x49000050)
#define HcRhPortSts1_REG    __REG(0x49000054)
#define HcRhPortSts2_REG    __REG(0x49000058)
/*
 * Interrupt
 */
#define ELFIN_INTERRUPT_BASE    0x4a000000
#define SRCPND_OFFSET        0x00
#define INTMOD_OFFSET        0x04
#define INTMSK_OFFSET        0x08
#define PRIORITY_OFFSET        0x0c
#define INTPND_OFFSET        0x10
#define INTOFFSET_OFFSET    0x14
#define SUBSRCPND_OFFSET    0x18
#define INTSUBMSK_OFFSET    0x1c
#define SRCPND_REG        __REG(0x4a000000)
#define INTMOD_REG        __REG(0x4a000004)
#define INTMSK_REG        __REG(0x4a000008)
#define PRIORITY_REG        __REG(0x4a00000c)
#define INTPND_REG        __REG(0x4a000010)
#define INTOFFSET_REG        __REG(0x4a000014)
#define SUBSRCPND_REG        __REG(0x4a000018)
#define INTSUBMSK_REG        __REG(0x4a00001C)
/*
 * Clock and power management
 */
#define ELFIN_CLOCK_POWER_BASE    0x4c000000
#define LOCKTIME_OFFSET        0x00
#define MPLLCON_OFFSET        0x04
#define UPLLCON_OFFSET        0x08
#define CLKCON_OFFSET        0x0c
#define CLKSLOW_OFFSET        0x10
#define CLKDIVN_OFFSET        0x14
#define CAMDIVN_OFFSET        0x18
#define LOCKTIME_REG        __REG(0x4c000000)
#define MPLLCON_REG        __REG(0x4c000004)
#define UPLLCON_REG        __REG(0x4c000008)
#define CLKCON_REG        __REG(0x4c00000c)
#define CLKSLOW_REG        __REG(0x4c000010)
#define CLKDIVN_REG        __REG(0x4c000014)
#define CAMDIVN_REG        __REG(0x4c000018)
/*
 * LCD Controller
 */
#define ELFIN_LCD_BASE        0x4d000000
/*
 * GPIO
 */
#define ELFIN_GPIO_BASE    0x56000000
#define GPACON_OFFSET        0x00
#define GPADAT_OFFSET        0x04
#define GPAPU_OFFSET        0x08
#define GPASLPCON_OFFSET    0x0C
#define GPABON_OFFSET        0x10
#define GPBDAT_OFFSET        0x14
#define GPBPU_OFFSET        0x18
#define GPBSLPCON_OFFSET    0x1C
#define GPCCON_OFFSET        0x20
#define GPCDAT_OFFSET        0x24
#define GPCPU_OFFSET        0x28
#define GPCSLPCON_OFFSET    0x2C
#define GPDCON_OFFSET        0x30
#define GPDDAT_OFFSET        0x34
#define GPDPU_OFFSET        0x38
#define GPECON_OFFSET        0x40
#define GPEDAT_OFFSET        0x44
#define GPEPU_OFFSET        0x48
#define GPESLPCON_OFFSET    0x4C
#define GPFCON_OFFSET        0x50
#define GPFDAT_OFFSET        0x54
#define GPFPU_OFFSET        0x58
#define GPFSLPCON_OFFSET    0x5C
#define GPGCON_OFFSET        0x60
#define GPGDAT_OFFSET        0x64
#define GPGPU_OFFSET        0x68
#define GPGSLPCON_OFFSET    0x6C
#define GPHCON_OFFSET        0x70
#define GPHDAT_OFFSET        0x74
#define GPHPU_OFFSET        0x78
#define GPHSLPCON_OFFSET    0x7C
#define GPICON_OFFSET        0x80
#define GPIDAT_OFFSET        0x84
#define GPIPU_OFFSET        0x88
#define GPISLPCON_OFFSET    0x8C
#define GPJCON_OFFSET        0x90
#define GPJDAT_OFFSET        0x94
#define GPJPU_OFFSET        0x98
#define SPCON_OFFSET        0x9C
#define GPKCON_OFFSET        0xA0
#define GPKDAT_OFFSET        0xA4
#define GPKPU_OFFSET        0xA8
#define GPKSLPCON_OFFSET    0xAC
#define EINTCON0_OFFSET        0xB0
#define EINTCON1_OFFSET        0xB4
#define EINTFLT0_OFFSET        0xB8
#define EINTFLT1_OFFSET        0xBC
#define EINTMASK_OFFSET        0xC0
#define EINTPEND_OFFSET        0xC4
#define DSPGPSLP_OFFSET        0xC8
#define MEM0CONSTOP_OFFSET    0xD0
#define MEM1CONSTOP_OFFSET    0xD4
#define MEM2CONSTOP_OFFSET    0xD8
#define MEM0CONSLP_OFFSET    0xE0
#define MEM1CONSLP_OFFSET    0xE4
#define MEM2CONSLP_OFFSET    0xE8
#define SPCONSLP_OFFSET        0xEC
#define SLPEN_OFFSET        0xF0
#define MEM0DRVCON_OFFSET    0xF4
#define MEM1DRVCON_OFFSET    0xF8
#define MEM2DRVCON_OFFSET    0xFC
#define GPACON_REG        __REG(0x44800000)
#define GPADAT_REG        __REG(0x44800004)
#define GPAPU_REG        __REG(0x44800008)
#define GPASLPCON_REG        __REG(0x4480000C)
#define GPABON_REG        __REG(0x44800010)
#define GPBDAT_REG        __REG(0x44800014)
#define GPBPU_REG        __REG(0x44800018)
#define GPBSLPCON_REG        __REG(0x4480001C)
#define GPCCON_REG        __REG(0x44800020)
#define GPCDAT_REG        __REG(0x44800024)
#define GPCPU_REG        __REG(0x44800028)
#define GPCSLPCON_REG        __REG(0x4480002C)
#define GPDCON_REG        __REG(0x44800030)
#define GPDDAT_REG        __REG(0x44800034)
#define GPDPU_REG        __REG(0x44800038)
#define GPECON_REG        __REG(0x44800040)
#define GPEDAT_REG        __REG(0x44800044)
#define GPEPU_REG        __REG(0x44800048)
#define GPESLPCON_REG        __REG(0x4480004C)
#define GPFCON_REG        __REG(0x44800050)
#define GPFDAT_REG        __REG(0x44800054)
#define GPFPU_REG        __REG(0x44800058)
#define GPFSLPCON_REG        __REG(0x4480005C)
#define GPGCON_REG        __REG(0x44800060)
#define GPGDAT_REG        __REG(0x44800064)
#define GPGPU_REG        __REG(0x44800068)
#define GPGSLPCON_REG        __REG(0x4480006C)
#define GPHCON_REG        __REG(0x44800070)
#define GPHDAT_REG        __REG(0x44800074)
#define GPHPU_REG        __REG(0x44800078)
#define GPHSLPCON_REG        __REG(0x4480007C)
#define GPICON_REG        __REG(0x44800080)
#define GPIDAT_REG        __REG(0x44800084)
#define GPIPU_REG        __REG(0x44800088)
#define GPISLPCON_REG        __REG(0x4480008C)
#define GPJCON_REG        __REG(0x44800090)
#define GPJDAT_REG        __REG(0x44800094)
#define GPJPU_REG        __REG(0x44800098)
#define SPCON_REG        __REG(0x4480009C)
#define GPKCON_REG        __REG(0x448000A0)
#define GPKDAT_REG        __REG(0x448000A4)
#define GPKPU_REG        __REG(0x448000A8)
#define GPKSLPCON_REG        __REG(0x448000AC)
#define EINTCON0_REG        __REG(0x448000B0)
#define EINTCON1_REG        __REG(0x448000B4)
#define EINTFLT0_REG        __REG(0x448000B8)
#define EINTFLT1_REG        __REG(0x448000BC)
#define EINTMASK_REG        __REG(0x448000C0)
#define EINTPEND_REG        __REG(0x448000C4)
#define DSPGPSLP_REG        __REG(0x448000C8)
#define MEM0CONSTOP_REG        __REG(0x448000D0)
#define MEM1CONSTOP_REG        __REG(0x448000D4)
#define MEM2CONSTOP_REG        __REG(0x448000D8)
#define MEM0CONSLP_REG        __REG(0x448000E0)
#define MEM1CONSLP_REG        __REG(0x448000E4)
#define MEM2CONSLP_REG        __REG(0x448000E8)
#define SPCONSLP_REG        __REG(0x448000EC)
#define SLPEN_REG        __REG(0x448000F0)
#define MEM0DRVCON_REG        __REG(0x448000F4)
#define MEM1DRVCON_REG        __REG(0x448000F8)
#define MEM2DRVCON_REG        __REG(0x448000FC)
/*
 * Nand flash controller
 */
#define ELFIN_NAND_BASE    0x4e000000
#define NFCONF_OFFSET        0x00
#define NFCONT_OFFSET        0x04
#define NFCMMD_OFFSET        0x08
#define NFADDR_OFFSET        0x0c
#define NFDATA_OFFSET        0x10
#define NFMECCD0_OFFSET        0x14
#define NFMECCD1_OFFSET        0x18
#define NFSECCD_OFFSET        0x1c
#define NFSTAT_OFFSET        0x20
#define NFESTAT0_OFFSET        0x24
#define NFESTAT1_OFFSET        0x28
#define NFMECC0_OFFSET        0x2c
#define NFMECC1_OFFSET        0x30
#define NFSECC_OFFSET        0x34
#define NFSBLK_OFFSET        0x38
#define NFEBLK_OFFSET        0x3c
#define NFCONF        (0x4e000000)
#define NFCONT        (0x4e000004)
#define NFCMMD        (0x4e000008)
#define NFADDR        (0x4e00000C)
#define NFDATA        (0x4e000010)
#define NFMECCDATA0    (0x4e000014)
#define NFMECCDATA1    (0x4e000018)
#define NFSECCDATA    (0x4e00001c)
#define NFSTAT        (0x4e000020)
#define NFESTAT0    (0x4e000024)
#define NFESTAT1    (0x4e000028)
#define NFMECC0        (0x4e00002C)
#define NFMECC1        (0x4e000030)
#define NFSECC        (0x4e00003c)
#define NFCONF_REG        __REG(0x4e000000)
#define NFCONT_REG        __REG(0x4e000004)
#define NFCMD_REG        __REGb(0x4e000008)
#define NFADDR_REG        __REGb(0x4e00000C)
#define NFDATA8_REG        __REGb(0x4e000010)
#define NFDATA16_REG        __REGw(0x4e000010)
#define NFDATA32_REG        __REG(0x4e000010)
#define NFSTAT_REG        __REG(0x4e000020)
#define NFCONT_WP        (1<<12)
#define NFCONT_SECCLOCK        (1<<6)
#define NFCONT_MECCLOCK        (1<<5)
#define NFCONT_INITECC        (1<<4)
#define NFCONT_CS_ALT        (1<<1)
#define NFCONT_CS        (1<<1)
#define NFSTAT_RnB        (1<<0)
/*
 * Watchdog timer
 */
#define ELFIN_WATCHDOG_BASE    0x53000000
#define WTCON_OFFSET        0x00
#define WTDAT_OFFSET        0x04
#define WTCNT_OFFSET        0x08
#define WTCON_REG        __REG(0x53000000)
#define WTDAT_REG        __REG(0x53000004)
#define WTCNT_REG        __REG(0x53000008)
/*
 * UART
 */
#define ELFIN_UART_BASE        0x50000000
#define ULCON0_OFFSET        0x00
#define UCON0_OFFSET        0x04
#define UFCON0_OFFSET        0x08
#define UMCON0_OFFSET        0x0C
#define UTRSTAT0_OFFSET        0x10
#define UERSTAT0_OFFSET        0x14
#define UFSTAT0_OFFSET        0x18
#define UMSTAT0_OFFSET        0x1C
#define UTXH0_OFFSET        0x20
#define URXH0_OFFSET        0x24
#define UBRDIV0_OFFSET        0x28
#define ULCON0_REG        __REG(0x50000000)
#define UCON0_REG        __REG(0x50000004)
#define UFCON0_REG        __REG(0x50000008)
#define UMCON0_REG        __REG(0x5000000C)
#define UTRSTAT0_REG        __REG(0x50000010)
#define UERSTAT0_REG        __REG(0x50000014)
#define UFSTAT0_REG        __REG(0x50000018)
#define UMSTAT0_REG        __REG(0x5000001C)
#define UTXH0_REG        __REG(0x50000020)
#define URXH0_REG        __REG(0x50000024)
#define UBRDIV0_REG        __REG(0x50000028)
#define ULCON1_REG        __REG(0x50004000)
#define UCON1_REG        __REG(0x50004004)
#define UFCON1_REG        __REG(0x50004008)
#define UMCON1_REG        __REG(0x5000400C)
#define UTRSTAT1_REG        __REG(0x50004010)
#define UERSTAT1_REG        __REG(0x50004014)
#define UFSTAT1_REG        __REG(0x50004018)
#define UMSTAT1_REG        __REG(0x5000401C)
#define UTXH1_REG        __REG(0x50004020)
#define URXH1_REG        __REG(0x50004024)
#define UBRDIV1_REG        __REG(0x50004028)
#define ULCON2_REG        __REG(0x50008000)
#define UCON2_REG        __REG(0x50008004)
#define UFCON2_REG        __REG(0x50008008)
#define UMCON2_REG        __REG(0x5000800C)
#define UTRSTAT2_REG        __REG(0x50008010)
#define UERSTAT2_REG        __REG(0x50008014)
#define UFSTAT2_REG        __REG(0x50008018)
#define UMSTAT2_REG        __REG(0x5000801C)
#define UTXH2_REG        __REG(0x50008020)
#define URXH2_REG        __REG(0x50008024)
#define UBRDIV2_REG        __REG(0x50008028)
#define UTRSTAT_TX_EMPTY    (1 << 2)
#define UTRSTAT_RX_READY    (1 << 0)
#define UART_ERR_MASK        0xF
/*
 * PWM timer
 */
#define ELFIN_TIMER_BASE    0x51000000
#define TCFG0_REG        __REG(0x51000000)
#define TCFG1_REG        __REG(0x51000004)
#define TCON_REG        __REG(0x51000008)
#define TCNTB0_REG        __REG(0x5100000C)
#define TCMPB0_REG        __REG(0x51000010)
#define TCNTO0_REG        __REG(0x51000014)
#define TCNTB1_REG        __REG(0x51000018)
#define TCMPB1_REG        __REG(0x5100001C)
#define TCNTO1_REG        __REG(0x51000020)
#define TCNTB2_REG        __REG(0x51000024)
#define TCMPB2_REG        __REG(0x51000028)
#define TCNTO2_REG        __REG(0x5100002C)
#define TCNTB3_REG        __REG(0x51000030)
#define TCMPB3_REG        __REG(0x51000034)
#define TCNTO3_REG        __REG(0x51000038)
#define TCNTB4_REG        __REG(0x5100003C)
#define TCNTO4_REG        __REG(0x51000040)
/* Fields */
#define fTCFG0_DZONE        Fld(8,16)   /* the dead zone length (= timer 0) */
#define fTCFG0_PRE1        Fld(8,8)    /* prescaler value for time 2,3,4 */
#define fTCFG0_PRE0        Fld(8,0)    /* prescaler value for time 0,1 */
#define fTCFG1_MUX4        Fld(4,16)
/* bits */
#define TCFG0_DZONE(x)        FInsrt((x), fTCFG0_DZONE)
#define TCFG0_PRE1(x)        FInsrt((x), fTCFG0_PRE1)
#define TCFG0_PRE0(x)        FInsrt((x), fTCFG0_PRE0)
#define TCON_4_AUTO        (1 << 22)   /* auto reload on/off for Timer 4 */
#define TCON_4_UPDATE        (1 << 21)   /* manual Update TCNTB4 */
#define TCON_4_ONOFF        (1 << 20)   /* 0: Stop, 1: start Timer 4 */
#define COUNT_4_ON        (TCON_4_ONOFF*1)
#define COUNT_4_OFF        (TCON_4_ONOFF*0)
#define TCON_3_AUTO        (1 << 19)   /* auto reload on/off for Timer 3 */
#define TIMER3_ATLOAD_ON    (TCON_3_AUTO*1)
#define TIMER3_ATLAOD_OFF    FClrBit(TCON, TCON_3_AUTO)
#define TCON_3_INVERT        (1 << 18)   /* 1: Inverter on for TOUT3 */
#define TIMER3_IVT_ON        (TCON_3_INVERT*1)
#define TIMER3_IVT_OFF        (FClrBit(TCON, TCON_3_INVERT))
#define TCON_3_MAN        (1 << 17)   /* manual Update TCNTB3,TCMPB3 */
#define TIMER3_MANUP        (TCON_3_MAN*1)
#define TIMER3_NOP        (FClrBit(TCON, TCON_3_MAN))
#define TCON_3_ONOFF        (1 << 16)   /* 0: Stop, 1: start Timer 3 */
#define TIMER3_ON        (TCON_3_ONOFF*1)
#define TIMER3_OFF        (FClrBit(TCON, TCON_3_ONOFF))
/* macros */
#define GET_PRESCALE_TIMER4(x)    FExtr((x), fTCFG0_PRE1)
#define GET_DIVIDER_TIMER4(x)    FExtr((x), fTCFG1_MUX4)
/*
 * RTC Controller
 */
#define ELFIN_RTC_BASE        0x57000000
#define RTCCON_REG        __REG(0x57000040)
#define TICNT_REG        __REG(0x57000044)
#define RTCALM_REG        __REG(0x57000050)
#define ALMSEC_REG        __REG(0x57000054)
#define ALMMIN_REG        __REG(0x57000058)
#define ALMHOUR_REG        __REG(0x5700005c)
#define ALMDATE_REG        __REG(0x57000060)
#define ALMMON_REG        __REG(0x57000064)
#define ALMYEAR_REG        __REG(0x57000068)
#define BCDSEC_REG        __REG(0x57000070)
#define BCDMIN_REG        __REG(0x57000074)
#define BCDHOUR_REG        __REG(0x57000078)
#define BCDDATE_REG        __REG(0x5700007c)
#define BCDDAY_REG        __REG(0x57000080)
#define BCDMON_REG        __REG(0x57000084)
#define BCDYEAR_REG        __REG(0x57000088)
/* USB Device */
#define ELFIN_USBD_BASE        0x52000000
#define USB_DEVICE_PHYS_ADR    ELFIN_USBD_BASE
/* include common stuff */
#ifndef __ASSEMBLY__
static inline S3C24X0_MEMCTL *S3C24X0_GetBase_MEMCTL(void)
{
    return (S3C24X0_MEMCTL *) (ELFIN_MEM_CON_BASE);
}
static inline S3C24X0_USB_HOST *S3C24X0_GetBase_USB_HOST(void)
{
    return (S3C24X0_USB_HOST *) ELFIN_USB_HOST_BASE;
}
static inline S3C24X0_INTERRUPT *S3C24X0_GetBase_INTERRUPT(void)
{
    return (S3C24X0_INTERRUPT *) ELFIN_INTERRUPT_BASE;
}
static inline S3C24X0_DMAS *S3C24X0_GetBase_DMAS(void)
{
    return (S3C24X0_DMAS *) ELFIN_DMA_BASE;
}
static inline S3C24X0_CLOCK_POWER *S3C24X0_GetBase_CLOCK_POWER(void)
{
    return (S3C24X0_CLOCK_POWER *) ELFIN_CLOCK_POWER_BASE;
}
static inline S3C24X0_LCD *S3C24X0_GetBase_LCD(void)
{
    return (S3C24X0_LCD *) ELFIN_LCD_BASE;
}
static inline S3C2410_NAND *S3C2410_GetBase_NAND(void)
{
    return (S3C2410_NAND *) ELFIN_NAND_BASE;
}
static inline S3C24X0_UART *S3C24X0_GetBase_UART(S3C24X0_UARTS_NR nr)
{
    return (S3C24X0_UART *) (ELFIN_UART_BASE + (nr * 0x4000));
}
static inline S3C24X0_TIMERS *S3C24X0_GetBase_TIMERS(void)
{
    return (S3C24X0_TIMERS *) ELFIN_TIMER_BASE;
}
static inline S3C24X0_USB_DEVICE *S3C24X0_GetBase_USB_DEVICE(void)
{
    return (S3C24X0_USB_DEVICE *) ELFIN_USB_DEVICE_BASE;
}
static inline S3C24X0_WATCHDOG *S3C24X0_GetBase_WATCHDOG(void)
{
    return (S3C24X0_WATCHDOG *) ELFIN_WATCHDOG_BASE;
}
static inline S3C24X0_I2C *S3C24X0_GetBase_I2C(void)
{
    return (S3C24X0_I2C *) ELFIN_I2C_BASE;
}
static inline S3C24X0_I2S *S3C24X0_GetBase_I2S(void)
{
    return (S3C24X0_I2S *) ELFIN_I2S_BASE;
}
static inline S3C24X0_GPIO *S3C24X0_GetBase_GPIO(void)
{
    return (S3C24X0_GPIO *) ELFIN_GPIO_BASE;
}
static inline S3C24X0_RTC *S3C24X0_GetBase_RTC(void)
{
    return (S3C24X0_RTC *) ELFIN_RTC_BASE;
}
static inline S3C2410_ADC *S3C2410_GetBase_ADC(void)
{
    return (S3C2410_ADC *) ELFIN_ADC_BASE;
}
static inline S3C24X0_SPI *S3C24X0_GetBase_SPI(void)
{
    return (S3C24X0_SPI *) ELFIN_SPI_BASE;
}
static inline S3C2410_SDI *S3C2410_GetBase_SDI(void)
{
    return (S3C2410_SDI *) ELFIN_SDI_BASE;
}
#else                           /* #ifndef __ASSEMBLY__ */
/* watchdog */
#define WTCON_OFFSET        0x00
/* LCD controller */
#define LCDBGCON_OFFSET        0x5c
#endif                          /* #ifndef __ASSEMBLY__ */
/* PENDING BIT */
#define BIT_EINT0        (0x1)
#define BIT_EINT1        (0x1<<1)
#define BIT_EINT2        (0x1<<2)
#define BIT_EINT3        (0x1<<3)
#define BIT_EINT4_7        (0x1<<4)
#define BIT_EINT8_23        (0x1<<5)
#define BIT_BAT_FLT        (0x1<<7)
#define BIT_TICK        (0x1<<8)
#define BIT_WDT            (0x1<<9)
#define BIT_TIMER0        (0x1<<10)
#define BIT_TIMER1        (0x1<<11)
#define BIT_TIMER2        (0x1<<12)
#define BIT_TIMER3        (0x1<<13)
#define BIT_TIMER4        (0x1<<14)
#define BIT_UART2        (0x1<<15)
#define BIT_LCD            (0x1<<16)
#define BIT_DMA0        (0x1<<17)
#define BIT_DMA1        (0x1<<18)
#define BIT_DMA2        (0x1<<19)
#define BIT_DMA3        (0x1<<20)
#define BIT_SDI            (0x1<<21)
#define BIT_SPI0        (0x1<<22)
#define BIT_UART1        (0x1<<23)
#define BIT_USBH        (0x1<<26)
#define BIT_IIC            (0x1<<27)
#define BIT_UART0        (0x1<<28)
#define BIT_SPI1        (0x1<<29)
#define BIT_RTC            (0x1<<30)
#define BIT_ADC            (0x1<<31)
#define BIT_ALLMSK        (0xFFFFFFFF)
#define CLKCON_USBD        (1<< 15)
#define BIT19            0x00080000
#define BIT29            0x20000000
#define BIT_USBD        BIT29
#define BIT_USBD_SUB        BIT19
#define ClearPending(bit) {\
         rSRCPND = bit;\
         rINTPND = bit;\
         rINTPND;\
         }
/* Wait until rINTPND is changed for the case that the ISR is very short. */
#endif /*__S3C2440_H__*/
linux-bsp/asm-study/myboot/include/s3c24x0.h
New file
@@ -0,0 +1,1125 @@
/*
 * (C) Copyright 2003
 * David Müller ELSOFT AG Switzerland. d.mueller@elsoft.ch
 *
 * 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
 */
/************************************************
 * NAME        : s3c24x0.h
 * Version  : 31.3.2003
 *
 * common stuff for SAMSUNG S3C24X0 SoC
 ************************************************/
#ifndef __S3C24X0_H__
#define __S3C24X0_H__
#include <asm/types.h>
typedef volatile u8 S3C24X0_REG8;
typedef volatile u16 S3C24X0_REG16;
typedef volatile u32 S3C24X0_REG32;
/* Memory controller (see manual chapter 5) */
typedef struct
{
    S3C24X0_REG32 BWSCON;
    S3C24X0_REG32 BANKCON[8];
    S3C24X0_REG32 REFRESH;
    S3C24X0_REG32 BANKSIZE;
    S3C24X0_REG32 MRSRB6;
    S3C24X0_REG32 MRSRB7;
} /*__attribute__((__packed__))*/ S3C24X0_MEMCTL;
/* USB HOST (see manual chapter 12) */
typedef struct
{
    S3C24X0_REG32 HcRevision;
    S3C24X0_REG32 HcControl;
    S3C24X0_REG32 HcCommonStatus;
    S3C24X0_REG32 HcInterruptStatus;
    S3C24X0_REG32 HcInterruptEnable;
    S3C24X0_REG32 HcInterruptDisable;
    S3C24X0_REG32 HcHCCA;
    S3C24X0_REG32 HcPeriodCuttendED;
    S3C24X0_REG32 HcControlHeadED;
    S3C24X0_REG32 HcControlCurrentED;
    S3C24X0_REG32 HcBulkHeadED;
    S3C24X0_REG32 HcBuldCurrentED;
    S3C24X0_REG32 HcDoneHead;
    S3C24X0_REG32 HcRmInterval;
    S3C24X0_REG32 HcFmRemaining;
    S3C24X0_REG32 HcFmNumber;
    S3C24X0_REG32 HcPeriodicStart;
    S3C24X0_REG32 HcLSThreshold;
    S3C24X0_REG32 HcRhDescriptorA;
    S3C24X0_REG32 HcRhDescriptorB;
    S3C24X0_REG32 HcRhStatus;
    S3C24X0_REG32 HcRhPortStatus1;
    S3C24X0_REG32 HcRhPortStatus2;
} /*__attribute__((__packed__))*/ S3C24X0_USB_HOST;
/* INTERRUPT (see manual chapter 14) */
typedef struct
{
    S3C24X0_REG32 SRCPND;
    S3C24X0_REG32 INTMOD;
    S3C24X0_REG32 INTMSK;
    S3C24X0_REG32 PRIORITY;
    S3C24X0_REG32 INTPND;
    S3C24X0_REG32 INTOFFSET;
#ifdef CONFIG_S3C2410
    S3C24X0_REG32 SUBSRCPND;
    S3C24X0_REG32 INTSUBMSK;
#endif
} /*__attribute__((__packed__))*/ S3C24X0_INTERRUPT;
/* DMAS (see manual chapter 8) */
typedef struct
{
    S3C24X0_REG32 DISRC;
#ifdef CONFIG_S3C2410
    S3C24X0_REG32 DISRCC;
#endif
    S3C24X0_REG32 DIDST;
#ifdef CONFIG_S3C2410
    S3C24X0_REG32 DIDSTC;
#endif
    S3C24X0_REG32 DCON;
    S3C24X0_REG32 DSTAT;
    S3C24X0_REG32 DCSRC;
    S3C24X0_REG32 DCDST;
    S3C24X0_REG32 DMASKTRIG;
#ifdef CONFIG_S3C2400
    S3C24X0_REG32 res[1];
#endif
#ifdef CONFIG_S3C2410
    S3C24X0_REG32 res[7];
#endif
} /*__attribute__((__packed__))*/ S3C24X0_DMA;
typedef struct
{
    S3C24X0_DMA dma[4];
} /*__attribute__((__packed__))*/ S3C24X0_DMAS;
/* CLOCK & POWER MANAGEMENT (see S3C2400 manual chapter 6) */
/*                          (see S3C2410 manual chapter 7) */
typedef struct
{
    S3C24X0_REG32 LOCKTIME;
    S3C24X0_REG32 MPLLCON;
    S3C24X0_REG32 UPLLCON;
    S3C24X0_REG32 CLKCON;
    S3C24X0_REG32 CLKSLOW;
    S3C24X0_REG32 CLKDIVN;
} /*__attribute__((__packed__))*/ S3C24X0_CLOCK_POWER;
/* LCD CONTROLLER (see manual chapter 15) */
typedef struct
{
    S3C24X0_REG32 LCDCON1;
    S3C24X0_REG32 LCDCON2;
    S3C24X0_REG32 LCDCON3;
    S3C24X0_REG32 LCDCON4;
    S3C24X0_REG32 LCDCON5;
    S3C24X0_REG32 LCDSADDR1;
    S3C24X0_REG32 LCDSADDR2;
    S3C24X0_REG32 LCDSADDR3;
    S3C24X0_REG32 REDLUT;
    S3C24X0_REG32 GREENLUT;
    S3C24X0_REG32 BLUELUT;
    S3C24X0_REG32 res[8];
    S3C24X0_REG32 DITHMODE;
    S3C24X0_REG32 TPAL;
#ifdef CONFIG_S3C2410
    S3C24X0_REG32 LCDINTPND;
    S3C24X0_REG32 LCDSRCPND;
    S3C24X0_REG32 LCDINTMSK;
    S3C24X0_REG32 LPCSEL;
#endif
} /*__attribute__((__packed__))*/ S3C24X0_LCD;
/* NAND FLASH (see S3C2410 manual chapter 6) */
typedef struct
{
    S3C24X0_REG32 NFCONF;
    S3C24X0_REG32 NFCMD;
    S3C24X0_REG32 NFADDR;
    S3C24X0_REG32 NFDATA;
    S3C24X0_REG32 NFSTAT;
    S3C24X0_REG32 NFECC;
} /*__attribute__((__packed__))*/ S3C2410_NAND;
/* UART (see manual chapter 11) */
typedef struct
{
    S3C24X0_REG32 ULCON;
    S3C24X0_REG32 UCON;
    S3C24X0_REG32 UFCON;
    S3C24X0_REG32 UMCON;
    S3C24X0_REG32 UTRSTAT;
    S3C24X0_REG32 UERSTAT;
    S3C24X0_REG32 UFSTAT;
    S3C24X0_REG32 UMSTAT;
#ifdef __BIG_ENDIAN
    S3C24X0_REG8 res1[3];
    S3C24X0_REG8 UTXH;
    S3C24X0_REG8 res2[3];
    S3C24X0_REG8 URXH;
#else                           /* Little Endian */
    S3C24X0_REG8 UTXH;
    S3C24X0_REG8 res1[3];
    S3C24X0_REG8 URXH;
    S3C24X0_REG8 res2[3];
#endif
    S3C24X0_REG32 UBRDIV;
} /*__attribute__((__packed__))*/ S3C24X0_UART;
/* PWM TIMER (see manual chapter 10) */
typedef struct
{
    S3C24X0_REG32 TCNTB;
    S3C24X0_REG32 TCMPB;
    S3C24X0_REG32 TCNTO;
} /*__attribute__((__packed__))*/ S3C24X0_TIMER;
typedef struct
{
    S3C24X0_REG32 TCFG0;
    S3C24X0_REG32 TCFG1;
    S3C24X0_REG32 TCON;
    S3C24X0_TIMER ch[4];
    S3C24X0_REG32 TCNTB4;
    S3C24X0_REG32 TCNTO4;
} /*__attribute__((__packed__))*/ S3C24X0_TIMERS;
/* USB DEVICE (see manual chapter 13) */
typedef struct
{
#ifdef __BIG_ENDIAN
    S3C24X0_REG8 res[3];
    S3C24X0_REG8 EP_FIFO_REG;
#else                           /*  little endian */
    S3C24X0_REG8 EP_FIFO_REG;
    S3C24X0_REG8 res[3];
#endif
} /*__attribute__((__packed__))*/ S3C24X0_USB_DEV_FIFOS;
typedef struct
{
#ifdef __BIG_ENDIAN
    S3C24X0_REG8 res1[3];
    S3C24X0_REG8 EP_DMA_CON;
    S3C24X0_REG8 res2[3];
    S3C24X0_REG8 EP_DMA_UNIT;
    S3C24X0_REG8 res3[3];
    S3C24X0_REG8 EP_DMA_FIFO;
    S3C24X0_REG8 res4[3];
    S3C24X0_REG8 EP_DMA_TTC_L;
    S3C24X0_REG8 res5[3];
    S3C24X0_REG8 EP_DMA_TTC_M;
    S3C24X0_REG8 res6[3];
    S3C24X0_REG8 EP_DMA_TTC_H;
#else                           /*  little endian */
    S3C24X0_REG8 EP_DMA_CON;
    S3C24X0_REG8 res1[3];
    S3C24X0_REG8 EP_DMA_UNIT;
    S3C24X0_REG8 res2[3];
    S3C24X0_REG8 EP_DMA_FIFO;
    S3C24X0_REG8 res3[3];
    S3C24X0_REG8 EP_DMA_TTC_L;
    S3C24X0_REG8 res4[3];
    S3C24X0_REG8 EP_DMA_TTC_M;
    S3C24X0_REG8 res5[3];
    S3C24X0_REG8 EP_DMA_TTC_H;
    S3C24X0_REG8 res6[3];
#endif
} /*__attribute__((__packed__))*/ S3C24X0_USB_DEV_DMAS;
typedef struct
{
#ifdef __BIG_ENDIAN
    S3C24X0_REG8 res1[3];
    S3C24X0_REG8 FUNC_ADDR_REG;
    S3C24X0_REG8 res2[3];
    S3C24X0_REG8 PWR_REG;
    S3C24X0_REG8 res3[3];
    S3C24X0_REG8 EP_INT_REG;
    S3C24X0_REG8 res4[15];
    S3C24X0_REG8 USB_INT_REG;
    S3C24X0_REG8 res5[3];
    S3C24X0_REG8 EP_INT_EN_REG;
    S3C24X0_REG8 res6[15];
    S3C24X0_REG8 USB_INT_EN_REG;
    S3C24X0_REG8 res7[3];
    S3C24X0_REG8 FRAME_NUM1_REG;
    S3C24X0_REG8 res8[3];
    S3C24X0_REG8 FRAME_NUM2_REG;
    S3C24X0_REG8 res9[3];
    S3C24X0_REG8 INDEX_REG;
    S3C24X0_REG8 res10[7];
    S3C24X0_REG8 MAXP_REG;
    S3C24X0_REG8 res11[3];
    S3C24X0_REG8 EP0_CSR_IN_CSR1_REG;
    S3C24X0_REG8 res12[3];
    S3C24X0_REG8 IN_CSR2_REG;
    S3C24X0_REG8 res13[7];
    S3C24X0_REG8 OUT_CSR1_REG;
    S3C24X0_REG8 res14[3];
    S3C24X0_REG8 OUT_CSR2_REG;
    S3C24X0_REG8 res15[3];
    S3C24X0_REG8 OUT_FIFO_CNT1_REG;
    S3C24X0_REG8 res16[3];
    S3C24X0_REG8 OUT_FIFO_CNT2_REG;
#else                           /*  little endian */
    S3C24X0_REG8 FUNC_ADDR_REG;
    S3C24X0_REG8 res1[3];
    S3C24X0_REG8 PWR_REG;
    S3C24X0_REG8 res2[3];
    S3C24X0_REG8 EP_INT_REG;
    S3C24X0_REG8 res3[15];
    S3C24X0_REG8 USB_INT_REG;
    S3C24X0_REG8 res4[3];
    S3C24X0_REG8 EP_INT_EN_REG;
    S3C24X0_REG8 res5[15];
    S3C24X0_REG8 USB_INT_EN_REG;
    S3C24X0_REG8 res6[3];
    S3C24X0_REG8 FRAME_NUM1_REG;
    S3C24X0_REG8 res7[3];
    S3C24X0_REG8 FRAME_NUM2_REG;
    S3C24X0_REG8 res8[3];
    S3C24X0_REG8 INDEX_REG;
    S3C24X0_REG8 res9[7];
    S3C24X0_REG8 MAXP_REG;
    S3C24X0_REG8 res10[7];
    S3C24X0_REG8 EP0_CSR_IN_CSR1_REG;
    S3C24X0_REG8 res11[3];
    S3C24X0_REG8 IN_CSR2_REG;
    S3C24X0_REG8 res12[3];
    S3C24X0_REG8 OUT_CSR1_REG;
    S3C24X0_REG8 res13[7];
    S3C24X0_REG8 OUT_CSR2_REG;
    S3C24X0_REG8 res14[3];
    S3C24X0_REG8 OUT_FIFO_CNT1_REG;
    S3C24X0_REG8 res15[3];
    S3C24X0_REG8 OUT_FIFO_CNT2_REG;
    S3C24X0_REG8 res16[3];
#endif                          /*  __BIG_ENDIAN */
    S3C24X0_USB_DEV_FIFOS fifo[5];
    S3C24X0_USB_DEV_DMAS dma[5];
} /*__attribute__((__packed__))*/ S3C24X0_USB_DEVICE;
/* WATCH DOG TIMER (see manual chapter 18) */
typedef struct
{
    S3C24X0_REG32 WTCON;
    S3C24X0_REG32 WTDAT;
    S3C24X0_REG32 WTCNT;
} /*__attribute__((__packed__))*/ S3C24X0_WATCHDOG;
/* IIC (see manual chapter 20) */
typedef struct
{
    S3C24X0_REG32 IICCON;
    S3C24X0_REG32 IICSTAT;
    S3C24X0_REG32 IICADD;
    S3C24X0_REG32 IICDS;
} /*__attribute__((__packed__))*/ S3C24X0_I2C;
/* IIS (see manual chapter 21) */
typedef struct
{
#ifdef __BIG_ENDIAN
    S3C24X0_REG16 res1;
    S3C24X0_REG16 IISCON;
    S3C24X0_REG16 res2;
    S3C24X0_REG16 IISMOD;
    S3C24X0_REG16 res3;
    S3C24X0_REG16 IISPSR;
    S3C24X0_REG16 res4;
    S3C24X0_REG16 IISFCON;
    S3C24X0_REG16 res5;
    S3C24X0_REG16 IISFIFO;
#else                           /*  little endian */
    S3C24X0_REG16 IISCON;
    S3C24X0_REG16 res1;
    S3C24X0_REG16 IISMOD;
    S3C24X0_REG16 res2;
    S3C24X0_REG16 IISPSR;
    S3C24X0_REG16 res3;
    S3C24X0_REG16 IISFCON;
    S3C24X0_REG16 res4;
    S3C24X0_REG16 IISFIFO;
    S3C24X0_REG16 res5;
#endif
} /*__attribute__((__packed__))*/ S3C24X0_I2S;
/* I/O PORT (see manual chapter 9) */
typedef struct
{
#ifdef CONFIG_S3C2400
    S3C24X0_REG32 PACON;
    S3C24X0_REG32 PADAT;
    S3C24X0_REG32 PBCON;
    S3C24X0_REG32 PBDAT;
    S3C24X0_REG32 PBUP;
    S3C24X0_REG32 PCCON;
    S3C24X0_REG32 PCDAT;
    S3C24X0_REG32 PCUP;
    S3C24X0_REG32 PDCON;
    S3C24X0_REG32 PDDAT;
    S3C24X0_REG32 PDUP;
    S3C24X0_REG32 PECON;
    S3C24X0_REG32 PEDAT;
    S3C24X0_REG32 PEUP;
    S3C24X0_REG32 PFCON;
    S3C24X0_REG32 PFDAT;
    S3C24X0_REG32 PFUP;
    S3C24X0_REG32 PGCON;
    S3C24X0_REG32 PGDAT;
    S3C24X0_REG32 PGUP;
    S3C24X0_REG32 OPENCR;
    S3C24X0_REG32 MISCCR;
    S3C24X0_REG32 EXTINT;
#endif
#ifdef CONFIG_S3C2410
    S3C24X0_REG32 GPACON;
    S3C24X0_REG32 GPADAT;
    S3C24X0_REG32 res1[2];
    S3C24X0_REG32 GPBCON;
    S3C24X0_REG32 GPBDAT;
    S3C24X0_REG32 GPBUP;
    S3C24X0_REG32 res2;
    S3C24X0_REG32 GPCCON;
    S3C24X0_REG32 GPCDAT;
    S3C24X0_REG32 GPCUP;
    S3C24X0_REG32 res3;
    S3C24X0_REG32 GPDCON;
    S3C24X0_REG32 GPDDAT;
    S3C24X0_REG32 GPDUP;
    S3C24X0_REG32 res4;
    S3C24X0_REG32 GPECON;
    S3C24X0_REG32 GPEDAT;
    S3C24X0_REG32 GPEUP;
    S3C24X0_REG32 res5;
    S3C24X0_REG32 GPFCON;
    S3C24X0_REG32 GPFDAT;
    S3C24X0_REG32 GPFUP;
    S3C24X0_REG32 res6;
    S3C24X0_REG32 GPGCON;
    S3C24X0_REG32 GPGDAT;
    S3C24X0_REG32 GPGUP;
    S3C24X0_REG32 res7;
    S3C24X0_REG32 GPHCON;
    S3C24X0_REG32 GPHDAT;
    S3C24X0_REG32 GPHUP;
    S3C24X0_REG32 res8;
    S3C24X0_REG32 MISCCR;
    S3C24X0_REG32 DCLKCON;
    S3C24X0_REG32 EXTINT0;
    S3C24X0_REG32 EXTINT1;
    S3C24X0_REG32 EXTINT2;
    S3C24X0_REG32 EINTFLT0;
    S3C24X0_REG32 EINTFLT1;
    S3C24X0_REG32 EINTFLT2;
    S3C24X0_REG32 EINTFLT3;
    S3C24X0_REG32 EINTMASK;
    S3C24X0_REG32 EINTPEND;
    S3C24X0_REG32 GSTATUS0;
    S3C24X0_REG32 GSTATUS1;
    S3C24X0_REG32 GSTATUS2;
    S3C24X0_REG32 GSTATUS3;
    S3C24X0_REG32 GSTATUS4;
#endif
} /*__attribute__((__packed__))*/ S3C24X0_GPIO;
/* RTC (see manual chapter 17) */
typedef struct
{
#ifdef __BIG_ENDIAN
    S3C24X0_REG8 res1[67];
    S3C24X0_REG8 RTCCON;
    S3C24X0_REG8 res2[3];
    S3C24X0_REG8 TICNT;
    S3C24X0_REG8 res3[11];
    S3C24X0_REG8 RTCALM;
    S3C24X0_REG8 res4[3];
    S3C24X0_REG8 ALMSEC;
    S3C24X0_REG8 res5[3];
    S3C24X0_REG8 ALMMIN;
    S3C24X0_REG8 res6[3];
    S3C24X0_REG8 ALMHOUR;
    S3C24X0_REG8 res7[3];
    S3C24X0_REG8 ALMDATE;
    S3C24X0_REG8 res8[3];
    S3C24X0_REG8 ALMMON;
    S3C24X0_REG8 res9[3];
    S3C24X0_REG8 ALMYEAR;
    S3C24X0_REG8 res10[3];
    S3C24X0_REG8 RTCRST;
    S3C24X0_REG8 res11[3];
    S3C24X0_REG8 BCDSEC;
    S3C24X0_REG8 res12[3];
    S3C24X0_REG8 BCDMIN;
    S3C24X0_REG8 res13[3];
    S3C24X0_REG8 BCDHOUR;
    S3C24X0_REG8 res14[3];
    S3C24X0_REG8 BCDDATE;
    S3C24X0_REG8 res15[3];
    S3C24X0_REG8 BCDDAY;
    S3C24X0_REG8 res16[3];
    S3C24X0_REG8 BCDMON;
    S3C24X0_REG8 res17[3];
    S3C24X0_REG8 BCDYEAR;
#else                           /*  little endian */
    S3C24X0_REG8 res0[64];
    S3C24X0_REG8 RTCCON;
    S3C24X0_REG8 res1[3];
    S3C24X0_REG8 TICNT;
    S3C24X0_REG8 res2[11];
    S3C24X0_REG8 RTCALM;
    S3C24X0_REG8 res3[3];
    S3C24X0_REG8 ALMSEC;
    S3C24X0_REG8 res4[3];
    S3C24X0_REG8 ALMMIN;
    S3C24X0_REG8 res5[3];
    S3C24X0_REG8 ALMHOUR;
    S3C24X0_REG8 res6[3];
    S3C24X0_REG8 ALMDATE;
    S3C24X0_REG8 res7[3];
    S3C24X0_REG8 ALMMON;
    S3C24X0_REG8 res8[3];
    S3C24X0_REG8 ALMYEAR;
    S3C24X0_REG8 res9[3];
    S3C24X0_REG8 RTCRST;
    S3C24X0_REG8 res10[3];
    S3C24X0_REG8 BCDSEC;
    S3C24X0_REG8 res11[3];
    S3C24X0_REG8 BCDMIN;
    S3C24X0_REG8 res12[3];
    S3C24X0_REG8 BCDHOUR;
    S3C24X0_REG8 res13[3];
    S3C24X0_REG8 BCDDATE;
    S3C24X0_REG8 res14[3];
    S3C24X0_REG8 BCDDAY;
    S3C24X0_REG8 res15[3];
    S3C24X0_REG8 BCDMON;
    S3C24X0_REG8 res16[3];
    S3C24X0_REG8 BCDYEAR;
    S3C24X0_REG8 res17[3];
#endif
} /*__attribute__((__packed__))*/ S3C24X0_RTC;
/* ADC (see manual chapter 16) */
typedef struct
{
    S3C24X0_REG32 ADCCON;
    S3C24X0_REG32 ADCDAT;
} /*__attribute__((__packed__))*/ S3C2400_ADC;
/* ADC (see manual chapter 16) */
typedef struct
{
    S3C24X0_REG32 ADCCON;
    S3C24X0_REG32 ADCTSC;
    S3C24X0_REG32 ADCDLY;
    S3C24X0_REG32 ADCDAT0;
    S3C24X0_REG32 ADCDAT1;
} /*__attribute__((__packed__))*/ S3C2410_ADC;
/* SPI (see manual chapter 22) */
typedef struct
{
    S3C24X0_REG32 SPCON;
    S3C24X0_REG32 SPSTA;
    S3C24X0_REG32 SPPIN;
    S3C24X0_REG32 SPPRE;
    S3C24X0_REG32 SPTDAT;
    S3C24X0_REG32 SPRDAT;
    S3C24X0_REG32 res[2];
} __attribute__ ((__packed__)) S3C24X0_SPI_CHANNEL;
typedef struct
{
    S3C24X0_SPI_CHANNEL ch[S3C24X0_SPI_CHANNELS];
} /*__attribute__((__packed__))*/ S3C24X0_SPI;
/* MMC INTERFACE (see S3C2400 manual chapter 19) */
typedef struct
{
#ifdef __BIG_ENDIAN
    S3C24X0_REG8 res1[3];
    S3C24X0_REG8 MMCON;
    S3C24X0_REG8 res2[3];
    S3C24X0_REG8 MMCRR;
    S3C24X0_REG8 res3[3];
    S3C24X0_REG8 MMFCON;
    S3C24X0_REG8 res4[3];
    S3C24X0_REG8 MMSTA;
    S3C24X0_REG16 res5;
    S3C24X0_REG16 MMFSTA;
    S3C24X0_REG8 res6[3];
    S3C24X0_REG8 MMPRE;
    S3C24X0_REG16 res7;
    S3C24X0_REG16 MMLEN;
    S3C24X0_REG8 res8[3];
    S3C24X0_REG8 MMCR7;
    S3C24X0_REG32 MMRSP[4];
    S3C24X0_REG8 res9[3];
    S3C24X0_REG8 MMCMD0;
    S3C24X0_REG32 MMCMD1;
    S3C24X0_REG16 res10;
    S3C24X0_REG16 MMCR16;
    S3C24X0_REG8 res11[3];
    S3C24X0_REG8 MMDAT;
#else
    S3C24X0_REG8 MMCON;
    S3C24X0_REG8 res1[3];
    S3C24X0_REG8 MMCRR;
    S3C24X0_REG8 res2[3];
    S3C24X0_REG8 MMFCON;
    S3C24X0_REG8 res3[3];
    S3C24X0_REG8 MMSTA;
    S3C24X0_REG8 res4[3];
    S3C24X0_REG16 MMFSTA;
    S3C24X0_REG16 res5;
    S3C24X0_REG8 MMPRE;
    S3C24X0_REG8 res6[3];
    S3C24X0_REG16 MMLEN;
    S3C24X0_REG16 res7;
    S3C24X0_REG8 MMCR7;
    S3C24X0_REG8 res8[3];
    S3C24X0_REG32 MMRSP[4];
    S3C24X0_REG8 MMCMD0;
    S3C24X0_REG8 res9[3];
    S3C24X0_REG32 MMCMD1;
    S3C24X0_REG16 MMCR16;
    S3C24X0_REG16 res10;
    S3C24X0_REG8 MMDAT;
    S3C24X0_REG8 res11[3];
#endif
} /*__attribute__((__packed__))*/ S3C2400_MMC;
/* SD INTERFACE (see S3C2410 manual chapter 19) */
typedef struct
{
    S3C24X0_REG32 SDICON;
    S3C24X0_REG32 SDIPRE;
    S3C24X0_REG32 SDICARG;
    S3C24X0_REG32 SDICCON;
    S3C24X0_REG32 SDICSTA;
    S3C24X0_REG32 SDIRSP0;
    S3C24X0_REG32 SDIRSP1;
    S3C24X0_REG32 SDIRSP2;
    S3C24X0_REG32 SDIRSP3;
    S3C24X0_REG32 SDIDTIMER;
    S3C24X0_REG32 SDIBSIZE;
    S3C24X0_REG32 SDIDCON;
    S3C24X0_REG32 SDIDCNT;
    S3C24X0_REG32 SDIDSTA;
    S3C24X0_REG32 SDIFSTA;
#ifdef __BIG_ENDIAN
    S3C24X0_REG8 res[3];
    S3C24X0_REG8 SDIDAT;
#else
    S3C24X0_REG8 SDIDAT;
    S3C24X0_REG8 res[3];
#endif
    S3C24X0_REG32 SDIIMSK;
} /*__attribute__((__packed__))*/ S3C2410_SDI;
#if 0
/* Memory control */
#define rBWSCON            (*(volatile unsigned *)0x48000000)
#define rBANKCON0        (*(volatile unsigned *)0x48000004)
#define rBANKCON1        (*(volatile unsigned *)0x48000008)
#define rBANKCON2        (*(volatile unsigned *)0x4800000C)
#define rBANKCON3        (*(volatile unsigned *)0x48000010)
#define rBANKCON4        (*(volatile unsigned *)0x48000014)
#define rBANKCON5        (*(volatile unsigned *)0x48000018)
#define rBANKCON6        (*(volatile unsigned *)0x4800001C)
#define rBANKCON7        (*(volatile unsigned *)0x48000020)
#define rREFRESH        (*(volatile unsigned *)0x48000024)
#define rBANKSIZE        (*(volatile unsigned *)0x48000028)
#define rMRSRB6            (*(volatile unsigned *)0x4800002C)
#define rMRSRB7            (*(volatile unsigned *)0x48000030)
/* USB HOST */
#define rHcRevision        (*(volatile unsigned *)0x49000000)
#define rHcControl        (*(volatile unsigned *)0x49000004)
#define rHcCommonStatus        (*(volatile unsigned *)0x49000008)
#define rHcInterruptStatus    (*(volatile unsigned *)0x4900000C)
#define rHcInterruptEnable    (*(volatile unsigned *)0x49000010)
#define rHcInterruptDisable    (*(volatile unsigned *)0x49000014)
#define rHcHCCA            (*(volatile unsigned *)0x49000018)
#define rHcPeriodCuttendED    (*(volatile unsigned *)0x4900001C)
#define rHcControlHeadED    (*(volatile unsigned *)0x49000020)
#define rHcControlCurrentED    (*(volatile unsigned *)0x49000024)
#define rHcBulkHeadED        (*(volatile unsigned *)0x49000028)
#define rHcBuldCurrentED    (*(volatile unsigned *)0x4900002C)
#define rHcDoneHead        (*(volatile unsigned *)0x49000030)
#define rHcRmInterval        (*(volatile unsigned *)0x49000034)
#define rHcFmRemaining        (*(volatile unsigned *)0x49000038)
#define rHcFmNumber        (*(volatile unsigned *)0x4900003C)
#define rHcPeriodicStart    (*(volatile unsigned *)0x49000040)
#define rHcLSThreshold        (*(volatile unsigned *)0x49000044)
#define rHcRhDescriptorA    (*(volatile unsigned *)0x49000048)
#define rHcRhDescriptorB    (*(volatile unsigned *)0x4900004C)
#define rHcRhStatus        (*(volatile unsigned *)0x49000050)
#define rHcRhPortStatus1    (*(volatile unsigned *)0x49000054)
#define rHcRhPortStatus2    (*(volatile unsigned *)0x49000058)
/* INTERRUPT */
#define rSRCPND            (*(volatile unsigned *)0x4A000000)
#define rINTMOD            (*(volatile unsigned *)0x4A000004)
#define rINTMSK            (*(volatile unsigned *)0x4A000008)
#define rPRIORITY        (*(volatile unsigned *)0x4A00000C)
#define rINTPND            (*(volatile unsigned *)0x4A000010)
#define rINTOFFSET        (*(volatile unsigned *)0x4A000014)
#define rSUBSRCPND        (*(volatile unsigned *)0x4A000018)
#define rINTSUBMSK        (*(volatile unsigned *)0x4A00001C)
/* DMA */
#define rDISRC0            (*(volatile unsigned *)0x4B000000)
#define rDISRCC0        (*(volatile unsigned *)0x4B000004)
#define rDIDST0            (*(volatile unsigned *)0x4B000008)
#define rDIDSTC0        (*(volatile unsigned *)0x4B00000C)
#define rDCON0            (*(volatile unsigned *)0x4B000010)
#define rDSTAT0            (*(volatile unsigned *)0x4B000014)
#define rDCSRC0            (*(volatile unsigned *)0x4B000018)
#define rDCDST0            (*(volatile unsigned *)0x4B00001C)
#define rDMASKTRIG0        (*(volatile unsigned *)0x4B000020)
#define rDISRC1            (*(volatile unsigned *)0x4B000040)
#define rDISRCC1        (*(volatile unsigned *)0x4B000044)
#define rDIDST1            (*(volatile unsigned *)0x4B000048)
#define rDIDSTC1        (*(volatile unsigned *)0x4B00004C)
#define rDCON1            (*(volatile unsigned *)0x4B000050)
#define rDSTAT1            (*(volatile unsigned *)0x4B000054)
#define rDCSRC1            (*(volatile unsigned *)0x4B000058)
#define rDCDST1            (*(volatile unsigned *)0x4B00005C)
#define rDMASKTRIG1        (*(volatile unsigned *)0x4B000060)
#define rDISRC2            (*(volatile unsigned *)0x4B000080)
#define rDISRCC2        (*(volatile unsigned *)0x4B000084)
#define rDIDST2            (*(volatile unsigned *)0x4B000088)
#define rDIDSTC2        (*(volatile unsigned *)0x4B00008C)
#define rDCON2            (*(volatile unsigned *)0x4B000090)
#define rDSTAT2            (*(volatile unsigned *)0x4B000094)
#define rDCSRC2            (*(volatile unsigned *)0x4B000098)
#define rDCDST2            (*(volatile unsigned *)0x4B00009C)
#define rDMASKTRIG2        (*(volatile unsigned *)0x4B0000A0)
#define rDISRC3            (*(volatile unsigned *)0x4B0000C0)
#define rDISRCC3        (*(volatile unsigned *)0x4B0000C4)
#define rDIDST3            (*(volatile unsigned *)0x4B0000C8)
#define rDIDSTC3        (*(volatile unsigned *)0x4B0000CC)
#define rDCON3            (*(volatile unsigned *)0x4B0000D0)
#define rDSTAT3            (*(volatile unsigned *)0x4B0000D4)
#define rDCSRC3            (*(volatile unsigned *)0x4B0000D8)
#define rDCDST3            (*(volatile unsigned *)0x4B0000DC)
#define rDMASKTRIG3        (*(volatile unsigned *)0x4B0000E0)
/* CLOCK & POWER MANAGEMENT */
#define rLOCKTIME        (*(volatile unsigned *)0x4C000000)
#define rMPLLCON        (*(volatile unsigned *)0x4C000004)
#define rUPLLCON        (*(volatile unsigned *)0x4C000008)
#define rCLKCON            (*(volatile unsigned *)0x4C00000C)
#define rCLKSLOW        (*(volatile unsigned *)0x4C000010)
#define rCLKDIVN        (*(volatile unsigned *)0x4C000014)
/* LCD CONTROLLER */
#define rLCDCON1        (*(volatile unsigned *)0x4D000000)
#define rLCDCON2        (*(volatile unsigned *)0x4D000004)
#define rLCDCON3        (*(volatile unsigned *)0x4D000008)
#define rLCDCON4        (*(volatile unsigned *)0x4D00000C)
#define rLCDCON5        (*(volatile unsigned *)0x4D000010)
#define rLCDSADDR1        (*(volatile unsigned *)0x4D000014)
#define rLCDSADDR2        (*(volatile unsigned *)0x4D000018)
#define rLCDSADDR3        (*(volatile unsigned *)0x4D00001C)
#define rREDLUT            (*(volatile unsigned *)0x4D000020)
#define rGREENLUT        (*(volatile unsigned *)0x4D000024)
#define rBLUELUT        (*(volatile unsigned *)0x4D000028)
#define rDITHMODE        (*(volatile unsigned *)0x4D00004C)
#define rTPAL            (*(volatile unsigned *)0x4D000050)
#define rLCDINTPND        (*(volatile unsigned *)0x4D000054)
#define rLCDSRCPND        (*(volatile unsigned *)0x4D000058)
#define rLCDINTMSK        (*(volatile unsigned *)0x4D00005C)
/* NAND FLASH */
#define rNFCONF            (*(volatile unsigned *)0x4E000000)
#define rNFCMD            (*(volatile unsigned *)0x4E000004)
#define rNFADDR            (*(volatile unsigned *)0x4E000008)
#define rNFDATA            (*(volatile unsigned *)0x4E00000C)
#define rNFSTAT            (*(volatile unsigned *)0x4E000010)
#define rNFECC            (*(volatile unsigned *)0x4E000014)
/* UART */
#define rULCON0            (*(volatile unsigned *)0x50000000)
#define rUCON0            (*(volatile unsigned *)0x50000004)
#define rUFCON0            (*(volatile unsigned *)0x50000008)
#define rUMCON0            (*(volatile unsigned *)0x5000000C)
#define rUTRSTAT0        (*(volatile unsigned *)0x50000010)
#define rUERSTAT0        (*(volatile unsigned *)0x50000014)
#define rUFSTAT0        (*(volatile unsigned *)0x50000018)
#define rUMSTAT0        (*(volatile unsigned *)0x5000001C)
#define rUBRDIV0        (*(volatile unsigned *)0x50000028)
#define rULCON1            (*(volatile unsigned *)0x50004000)
#define rUCON1            (*(volatile unsigned *)0x50004004)
#define rUFCON1            (*(volatile unsigned *)0x50004008)
#define rUMCON1            (*(volatile unsigned *)0x5000400C)
#define rUTRSTAT1        (*(volatile unsigned *)0x50004010)
#define rUERSTAT1        (*(volatile unsigned *)0x50004014)
#define rUFSTAT1        (*(volatile unsigned *)0x50004018)
#define rUMSTAT1        (*(volatile unsigned *)0x5000401C)
#define rUBRDIV1        (*(volatile unsigned *)0x50004028)
#define rULCON2            (*(volatile unsigned *)0x50008000)
#define rUCON2            (*(volatile unsigned *)0x50008004)
#define rUFCON2            (*(volatile unsigned *)0x50008008)
#define rUTRSTAT2        (*(volatile unsigned *)0x50008010)
#define rUERSTAT2        (*(volatile unsigned *)0x50008014)
#define rUFSTAT2        (*(volatile unsigned *)0x50008018)
#define rUBRDIV2        (*(volatile unsigned *)0x50008028)
#ifdef __BIG_ENDIAN
#define rUTXH0            (*(volatile unsigned char *)0x50000023)
#define rURXH0            (*(volatile unsigned char *)0x50000027)
#define rUTXH1            (*(volatile unsigned char *)0x50004023)
#define rURXH1            (*(volatile unsigned char *)0x50004027)
#define rUTXH2            (*(volatile unsigned char *)0x50008023)
#define rURXH2            (*(volatile unsigned char *)0x50008027)
#define WrUTXH0(ch)        (*(volatile unsigned char *)0x50000023)=(unsigned char)(ch)
#define RdURXH0()        (*(volatile unsigned char *)0x50000027)
#define WrUTXH1(ch)        (*(volatile unsigned char *)0x50004023)=(unsigned char)(ch)
#define RdURXH1()        (*(volatile unsigned char *)0x50004027)
#define WrUTXH2(ch)        (*(volatile unsigned char *)0x50008023)=(unsigned char)(ch)
#define RdURXH2()        (*(volatile unsigned char *)0x50008027)
#define UTXH0            (0x50000020+3)  /* byte_access address by DMA */
#define URXH0            (0x50000024+3)
#define UTXH1            (0x50004020+3)
#define URXH1            (0x50004024+3)
#define UTXH2            (0x50008020+3)
#define URXH2            (0x50008024+3)
#else                           /* Little Endian */
#define rUTXH0            (*(volatile unsigned char *)0x50000020)
#define rURXH0            (*(volatile unsigned char *)0x50000024)
#define rUTXH1            (*(volatile unsigned char *)0x50004020)
#define rURXH1            (*(volatile unsigned char *)0x50004024)
#define rUTXH2            (*(volatile unsigned char *)0x50008020)
#define rURXH2            (*(volatile unsigned char *)0x50008024)
#define WrUTXH0(ch)        (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch)
#define RdURXH0()        (*(volatile unsigned char *)0x50000024)
#define WrUTXH1(ch)        (*(volatile unsigned char *)0x50004020)=(unsigned char)(ch)
#define RdURXH1()        (*(volatile unsigned char *)0x50004024)
#define WrUTXH2(ch)        (*(volatile unsigned char *)0x50008020)=(unsigned char)(ch)
#define RdURXH2()        (*(volatile unsigned char *)0x50008024)
#define UTXH0            (0x50000020)    /* byte_access address by DMA */
#define URXH0            (0x50000024)
#define UTXH1            (0x50004020)
#define URXH1            (0x50004024)
#define UTXH2            (0x50008020)
#define URXH2            (0x50008024)
#endif
/* PWM TIMER */
#define rTCFG0            (*(volatile unsigned *)0x51000000)
#define rTCFG1            (*(volatile unsigned *)0x51000004)
#define rTCON            (*(volatile unsigned *)0x51000008)
#define rTCNTB0            (*(volatile unsigned *)0x5100000C)
#define rTCMPB0            (*(volatile unsigned *)0x51000010)
#define rTCNTO0            (*(volatile unsigned *)0x51000014)
#define rTCNTB1            (*(volatile unsigned *)0x51000018)
#define rTCMPB1            (*(volatile unsigned *)0x5100001C)
#define rTCNTO1            (*(volatile unsigned *)0x51000020)
#define rTCNTB2            (*(volatile unsigned *)0x51000024)
#define rTCMPB2            (*(volatile unsigned *)0x51000028)
#define rTCNTO2            (*(volatile unsigned *)0x5100002C)
#define rTCNTB3            (*(volatile unsigned *)0x51000030)
#define rTCMPB3            (*(volatile unsigned *)0x51000034)
#define rTCNTO3            (*(volatile unsigned *)0x51000038)
#define rTCNTB4            (*(volatile unsigned *)0x5100003C)
#define rTCNTO4            (*(volatile unsigned *)0x51000040)
/* USB DEVICE */
#ifdef __BIG_ENDIAN
#define rFUNC_ADDR_REG        (*(volatile unsigned char *)0x52000143)
#define rPWR_REG        (*(volatile unsigned char *)0x52000147)
#define rEP_INT_REG        (*(volatile unsigned char *)0x5200014B)
#define rUSB_INT_REG        (*(volatile unsigned char *)0x5200015B)
#define rEP_INT_EN_REG        (*(volatile unsigned char *)0x5200015F)
#define rUSB_INT_EN_REG        (*(volatile unsigned char *)0x5200016F)
#define rFRAME_NUM1_REG        (*(volatile unsigned char *)0x52000173)
#define rFRAME_NUM2_REG        (*(volatile unsigned char *)0x52000177)
#define rINDEX_REG        (*(volatile unsigned char *)0x5200017B)
#define rMAXP_REG        (*(volatile unsigned char *)0x52000183)
#define rEP0_CSR        (*(volatile unsigned char *)0x52000187)
#define rIN_CSR1_REG        (*(volatile unsigned char *)0x52000187)
#define rIN_CSR2_REG        (*(volatile unsigned char *)0x5200018B)
#define rOUT_CSR1_REG        (*(volatile unsigned char *)0x52000193)
#define rOUT_CSR2_REG        (*(volatile unsigned char *)0x52000197)
#define rOUT_FIFO_CNT1_REG    (*(volatile unsigned char *)0x5200019B)
#define rOUT_FIFO_CNT2_REG    (*(volatile unsigned char *)0x5200019F)
#define rEP0_FIFO        (*(volatile unsigned char *)0x520001C3)
#define rEP1_FIFO        (*(volatile unsigned char *)0x520001C7)
#define rEP2_FIFO        (*(volatile unsigned char *)0x520001CB)
#define rEP3_FIFO        (*(volatile unsigned char *)0x520001CF)
#define rEP4_FIFO        (*(volatile unsigned char *)0x520001D3)
#define rEP1_DMA_CON        (*(volatile unsigned char *)0x52000203)
#define rEP1_DMA_UNIT        (*(volatile unsigned char *)0x52000207)
#define rEP1_DMA_FIFO        (*(volatile unsigned char *)0x5200020B)
#define rEP1_DMA_TX_LO        (*(volatile unsigned char *)0x5200020F)
#define rEP1_DMA_TX_MD        (*(volatile unsigned char *)0x52000213)
#define rEP1_DMA_TX_HI        (*(volatile unsigned char *)0x52000217)
#define rEP2_DMA_CON        (*(volatile unsigned char *)0x5200021B)
#define rEP2_DMA_UNIT        (*(volatile unsigned char *)0x5200021F)
#define rEP2_DMA_FIFO        (*(volatile unsigned char *)0x52000223)
#define rEP2_DMA_TX_LO        (*(volatile unsigned char *)0x52000227)
#define rEP2_DMA_TX_MD        (*(volatile unsigned char *)0x5200022B)
#define rEP2_DMA_TX_HI        (*(volatile unsigned char *)0x5200022F)
#define rEP3_DMA_CON        (*(volatile unsigned char *)0x52000243)
#define rEP3_DMA_UNIT        (*(volatile unsigned char *)0x52000247)
#define rEP3_DMA_FIFO        (*(volatile unsigned char *)0x5200024B)
#define rEP3_DMA_TX_LO        (*(volatile unsigned char *)0x5200024F)
#define rEP3_DMA_TX_MD        (*(volatile unsigned char *)0x52000253)
#define rEP3_DMA_TX_HI        (*(volatile unsigned char *)0x52000257)
#define rEP4_DMA_CON        (*(volatile unsigned char *)0x5200025B)
#define rEP4_DMA_UNIT        (*(volatile unsigned char *)0x5200025F)
#define rEP4_DMA_FIFO        (*(volatile unsigned char *)0x52000263)
#define rEP4_DMA_TX_LO        (*(volatile unsigned char *)0x52000267)
#define rEP4_DMA_TX_MD        (*(volatile unsigned char *)0x5200026B)
#define rEP4_DMA_TX_HI        (*(volatile unsigned char *)0x5200026F)
#else                           /*  little endian */
#define rFUNC_ADDR_REG        (*(volatile unsigned char *)0x52000140)
#define rPWR_REG        (*(volatile unsigned char *)0x52000144)
#define rEP_INT_REG        (*(volatile unsigned char *)0x52000148)
#define rUSB_INT_REG        (*(volatile unsigned char *)0x52000158)
#define rEP_INT_EN_REG        (*(volatile unsigned char *)0x5200015C)
#define rUSB_INT_EN_REG        (*(volatile unsigned char *)0x5200016C)
#define rFRAME_NUM1_REG        (*(volatile unsigned char *)0x52000170)
#define rFRAME_NUM2_REG        (*(volatile unsigned char *)0x52000174)
#define rINDEX_REG        (*(volatile unsigned char *)0x52000178)
#define rMAXP_REG        (*(volatile unsigned char *)0x52000180)
#define rEP0_CSR        (*(volatile unsigned char *)0x52000184)
#define rIN_CSR1_REG        (*(volatile unsigned char *)0x52000184)
#define rIN_CSR2_REG        (*(volatile unsigned char *)0x52000188)
#define rOUT_CSR1_REG        (*(volatile unsigned char *)0x52000190)
#define rOUT_CSR2_REG        (*(volatile unsigned char *)0x52000194)
#define rOUT_FIFO_CNT1_REG    (*(volatile unsigned char *)0x52000198)
#define rOUT_FIFO_CNT2_REG    (*(volatile unsigned char *)0x5200019C)
#define rEP0_FIFO        (*(volatile unsigned char *)0x520001C0)
#define rEP1_FIFO        (*(volatile unsigned char *)0x520001C4)
#define rEP2_FIFO        (*(volatile unsigned char *)0x520001C8)
#define rEP3_FIFO        (*(volatile unsigned char *)0x520001CC)
#define rEP4_FIFO        (*(volatile unsigned char *)0x520001D0)
#define rEP1_DMA_CON        (*(volatile unsigned char *)0x52000200)
#define rEP1_DMA_UNIT        (*(volatile unsigned char *)0x52000204)
#define rEP1_DMA_FIFO        (*(volatile unsigned char *)0x52000208)
#define rEP1_DMA_TX_LO        (*(volatile unsigned char *)0x5200020C)
#define rEP1_DMA_TX_MD        (*(volatile unsigned char *)0x52000210)
#define rEP1_DMA_TX_HI        (*(volatile unsigned char *)0x52000214)
#define rEP2_DMA_CON        (*(volatile unsigned char *)0x52000218)
#define rEP2_DMA_UNIT        (*(volatile unsigned char *)0x5200021C)
#define rEP2_DMA_FIFO        (*(volatile unsigned char *)0x52000220)
#define rEP2_DMA_TX_LO        (*(volatile unsigned char *)0x52000224)
#define rEP2_DMA_TX_MD        (*(volatile unsigned char *)0x52000228)
#define rEP2_DMA_TX_HI        (*(volatile unsigned char *)0x5200022C)
#define rEP3_DMA_CON        (*(volatile unsigned char *)0x52000240)
#define rEP3_DMA_UNIT        (*(volatile unsigned char *)0x52000244)
#define rEP3_DMA_FIFO        (*(volatile unsigned char *)0x52000248)
#define rEP3_DMA_TX_LO        (*(volatile unsigned char *)0x5200024C)
#define rEP3_DMA_TX_MD        (*(volatile unsigned char *)0x52000250)
#define rEP3_DMA_TX_HI        (*(volatile unsigned char *)0x52000254)
#define rEP4_DMA_CON        (*(volatile unsigned char *)0x52000258)
#define rEP4_DMA_UNIT        (*(volatile unsigned char *)0x5200025C)
#define rEP4_DMA_FIFO        (*(volatile unsigned char *)0x52000260)
#define rEP4_DMA_TX_LO        (*(volatile unsigned char *)0x52000264)
#define rEP4_DMA_TX_MD        (*(volatile unsigned char *)0x52000268)
#define rEP4_DMA_TX_HI        (*(volatile unsigned char *)0x5200026C)
#endif                          /*  __BIG_ENDIAN */
/* WATCH DOG TIMER */
#define rWTCON            (*(volatile unsigned *)0x53000000)
#define rWTDAT            (*(volatile unsigned *)0x53000004)
#define rWTCNT            (*(volatile unsigned *)0x53000008)
/* IIC */
#define rIICCON            (*(volatile unsigned *)0x54000000)
#define rIICSTAT        (*(volatile unsigned *)0x54000004)
#define rIICADD            (*(volatile unsigned *)0x54000008)
#define rIICDS            (*(volatile unsigned *)0x5400000C)
/* IIS */
#define rIISCON            (*(volatile unsigned *)0x55000000)
#define rIISMOD            (*(volatile unsigned *)0x55000004)
#define rIISPSR            (*(volatile unsigned *)0x55000008)
#define rIISFCON        (*(volatile unsigned *)0x5500000C)
#ifdef __BIG_ENDIAN
#define IISFIF            ((volatile unsigned short *)0x55000012)
#else                           /*  little endian */
#define IISFIF            ((volatile unsigned short *)0x55000010)
#endif
/* I/O PORT */
#define rGPACON            (*(volatile unsigned *)0x56000000)
#define rGPADAT            (*(volatile unsigned *)0x56000004)
#define rGPBCON            (*(volatile unsigned *)0x56000010)
#define rGPBDAT            (*(volatile unsigned *)0x56000014)
#define rGPBUP            (*(volatile unsigned *)0x56000018)
#define rGPCCON            (*(volatile unsigned *)0x56000020)
#define rGPCDAT            (*(volatile unsigned *)0x56000024)
#define rGPCUP            (*(volatile unsigned *)0x56000028)
#define rGPDCON            (*(volatile unsigned *)0x56000030)
#define rGPDDAT            (*(volatile unsigned *)0x56000034)
#define rGPDUP            (*(volatile unsigned *)0x56000038)
#define rGPECON            (*(volatile unsigned *)0x56000040)
#define rGPEDAT            (*(volatile unsigned *)0x56000044)
#define rGPEUP            (*(volatile unsigned *)0x56000048)
#define rGPFCON            (*(volatile unsigned *)0x56000050)
#define rGPFDAT            (*(volatile unsigned *)0x56000054)
#define rGPFUP            (*(volatile unsigned *)0x56000058)
#define rGPGCON            (*(volatile unsigned *)0x56000060)
#define rGPGDAT            (*(volatile unsigned *)0x56000064)
#define rGPGUP            (*(volatile unsigned *)0x56000068)
#define rGPHCON            (*(volatile unsigned *)0x56000070)
#define rGPHDAT            (*(volatile unsigned *)0x56000074)
#define rGPHUP            (*(volatile unsigned *)0x56000078)
#define rMISCCR            (*(volatile unsigned *)0x56000080)
#define rDCLKCON        (*(volatile unsigned *)0x56000084)
#define rEXTINT0        (*(volatile unsigned *)0x56000088)
#define rEXTINT1        (*(volatile unsigned *)0x5600008C)
#define rEXTINT2        (*(volatile unsigned *)0x56000090)
#define rEINTFLT0        (*(volatile unsigned *)0x56000094)
#define rEINTFLT1        (*(volatile unsigned *)0x56000098)
#define rEINTFLT2        (*(volatile unsigned *)0x5600009C)
#define rEINTFLT3        (*(volatile unsigned *)0x560000A0)
#define rEINTMASK        (*(volatile unsigned *)0x560000A4)
#define rEINTPEND        (*(volatile unsigned *)0x560000A8)
#define rGSTATUS0        (*(volatile unsigned *)0x560000AC)
#define rGSTATUS1        (*(volatile unsigned *)0x560000B0)
/* RTC */
#ifdef __BIG_ENDIAN
#define rRTCCON            (*(volatile unsigned char *)0x57000043)
#define rTICNT            (*(volatile unsigned char *)0x57000047)
#define rRTCALM            (*(volatile unsigned char *)0x57000053)
#define rALMSEC            (*(volatile unsigned char *)0x57000057)
#define rALMMIN            (*(volatile unsigned char *)0x5700005B)
#define rALMHOUR        (*(volatile unsigned char *)0x5700005F)
#define rALMDATE        (*(volatile unsigned char *)0x57000063)
#define rALMMON            (*(volatile unsigned char *)0x57000067)
#define rALMYEAR        (*(volatile unsigned char *)0x5700006B)
#define rRTCRST            (*(volatile unsigned char *)0x5700006F)
#define rBCDSEC            (*(volatile unsigned char *)0x57000073)
#define rBCDMIN            (*(volatile unsigned char *)0x57000077)
#define rBCDHOUR        (*(volatile unsigned char *)0x5700007B)
#define rBCDDATE        (*(volatile unsigned char *)0x5700007F)
#define rBCDDAY            (*(volatile unsigned char *)0x57000083)
#define rBCDMON            (*(volatile unsigned char *)0x57000087)
#define rBCDYEAR        (*(volatile unsigned char *)0x5700008B)
#else                           /*  little endian */
#define rRTCCON            (*(volatile unsigned char *)0x57000040)
#define rTICNT            (*(volatile unsigned char *)0x57000044)
#define rRTCALM            (*(volatile unsigned char *)0x57000050)
#define rALMSEC            (*(volatile unsigned char *)0x57000054)
#define rALMMIN            (*(volatile unsigned char *)0x57000058)
#define rALMHOUR        (*(volatile unsigned char *)0x5700005C)
#define rALMDATE        (*(volatile unsigned char *)0x57000060)
#define rALMMON            (*(volatile unsigned char *)0x57000064)
#define rALMYEAR        (*(volatile unsigned char *)0x57000068)
#define rRTCRST            (*(volatile unsigned char *)0x5700006C)
#define rBCDSEC            (*(volatile unsigned char *)0x57000070)
#define rBCDMIN            (*(volatile unsigned char *)0x57000074)
#define rBCDHOUR        (*(volatile unsigned char *)0x57000078)
#define rBCDDATE        (*(volatile unsigned char *)0x5700007C)
#define rBCDDAY            (*(volatile unsigned char *)0x57000080)
#define rBCDMON            (*(volatile unsigned char *)0x57000084)
#define rBCDYEAR        (*(volatile unsigned char *)0x57000088)
#endif
/* ADC */
#define rADCCON            (*(volatile unsigned *)0x58000000)
#define rADCTSC            (*(volatile unsigned *)0x58000004)
#define rADCDLY            (*(volatile unsigned *)0x58000008)
#define rADCDAT0        (*(volatile unsigned *)0x5800000C)
#define rADCDAT1        (*(volatile unsigned *)0x58000010)
/* SPI */
#define rSPCON0            (*(volatile unsigned *)0x59000000)
#define rSPSTA0            (*(volatile unsigned *)0x59000004)
#define rSPPIN0            (*(volatile unsigned *)0x59000008)
#define rSPPRE0            (*(volatile unsigned *)0x5900000C)
#define rSPTDAT0        (*(volatile unsigned *)0x59000010)
#define rSPRDAT0        (*(volatile unsigned *)0x59000014)
#define rSPCON1            (*(volatile unsigned *)0x59000020)
#define rSPSTA1            (*(volatile unsigned *)0x59000024)
#define rSPPIN1            (*(volatile unsigned *)0x59000028)
#define rSPPRE1            (*(volatile unsigned *)0x5900002C)
#define rSPTDAT1        (*(volatile unsigned *)0x59000030)
#define rSPRDAT1        (*(volatile unsigned *)0x59000034)
/* SD INTERFACE */
#define rSDICON            (*(volatile unsigned *)0x5A000000)
#define rSDIPRE            (*(volatile unsigned *)0x5A000004)
#define rSDICmdArg        (*(volatile unsigned *)0x5A000008)
#define rSDICmdCon        (*(volatile unsigned *)0x5A00000C)
#define rSDICmdSta        (*(volatile unsigned *)0x5A000010)
#define rSDIRSP0        (*(volatile unsigned *)0x5A000014)
#define rSDIRSP1        (*(volatile unsigned *)0x5A000018)
#define rSDIRSP2        (*(volatile unsigned *)0x5A00001C)
#define rSDIRSP3        (*(volatile unsigned *)0x5A000020)
#define rSDIDTimer        (*(volatile unsigned *)0x5A000024)
#define rSDIBSize        (*(volatile unsigned *)0x5A000028)
#define rSDIDatCon        (*(volatile unsigned *)0x5A00002C)
#define rSDIDatCnt        (*(volatile unsigned *)0x5A000030)
#define rSDIDatSta        (*(volatile unsigned *)0x5A000034)
#define rSDIFSTA        (*(volatile unsigned *)0x5A000038)
#ifdef __BIG_ENDIAN
#define rSDIDAT            (*(volatile unsigned char *)0x5A00003F)
#else
#define rSDIDAT            (*(volatile unsigned char *)0x5A00003C)
#endif
#define rSDIIntMsk        (*(volatile unsigned *)0x5A000040)
#endif
#endif /*__S3C24X0_H__*/
linux-bsp/asm-study/myboot/interrupt.c
New file
@@ -0,0 +1,39 @@
/********************************************************************************************
 *        File:  interrupt.c
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  The CPU interrupt vector table depends on function, called in start.S
 *   ChangeLog:  1, Release initial version on "Tue Jul 12 16:43:18 CST 2011"
 *
 *******************************************************************************************/
#include <common.h>
void do_undefined_instruction(void)
{
}
void do_software_interrupt(void)
{
}
void do_prefetch_abort(void)
{
}
void do_data_abort(void)
{
}
void do_not_used(void)
{
}
void do_irq(void)
{
}
void do_fiq(void)
{
}
linux-bsp/asm-study/myboot/k9f2g08.c
New file
@@ -0,0 +1,638 @@
/********************************************************************************************
 *        File:  k9f2g08.c: K9F2G08 read/write/erase functions for bootstrap
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  This C code is the first stage bootloader(named bootstrap)
                 main code, test on FL2440 board.
 *   ChangeLog:  1, Release initial version on "Tue Jul 12 16:43:18 CST 2011"
 *
 *******************************************************************************************/
/*************************************************************
 * Read Status Register Definition of K9F2G08(Refer to k9f2g08u0m datasheet)
 *
 * |-------------------------------------------------------------------------------------|
 * | I/O No. | Page Program | Block Erase | Cache Program |     Read    | Definition     |
 * |-------------------------------------------------------------------------------------|
 * | I/O 0   |  Pass/Fail   |  Pass/Fail  | Pass/Fail(N)  |   Not use   | Pass:0 Fail:1  |
 * |-------------------------------------------------------------------------------------|
 * | I/O 1   |  Not use     |  Not use    | Pass/Fail(N-1)|   Not use   | Pass:0 Fail:1  |
 * |-------------------------------------------------------------------------------------|
 * | I/O 2   |  Not use     |  Not use    | Not use       |   Not use   | Don't care     |
 * |-------------------------------------------------------------------------------------|
 * | I/O 3   |  Not use     |  Not use    | Not use       |   Not use   | Don't care     |
 * |-------------------------------------------------------------------------------------|
 * | I/O 4   |  Not use     |  Not use    | Not use       |   Not use   | Don't care     |
 * |-------------------------------------------------------------------------------------|
 * | I/O 5   |  Ready/Busy  |  Ready/Busy |True Ready/Busy| Ready/Busy  | Busy:0 Ready:1 |
 * |-------------------------------------------------------------------------------------|
 * | I/O 6   |  Ready/Busy  |  Ready/Busy | Ready/Busy    | Ready/Busy  | Busy:0 Ready:1 |
 * |-------------------------------------------------------------------------------------|
 * | I/O 7   |Write protect |Write protect| Write protect |Write protect| Protect:0 Not:1|
 * |-------------------------------------------------------------------------------------|
 *
 *************************************************************/
#include <nand.h>
/**
 * nand_read_id - Read the Nandflash ID
 * @nand:       The nand flash information
 * return:      The nandflash ID
 */
static unsigned short nand_read_id(void)
{
    unsigned short id = 0;
    nand_select(); /* chip Enable */
    nand_clear_RnB(); /*Clear Ready & Busy signal*/
    REG_NFCMD = NAND_CMD_READID; /*Read ID command*/
    REG_NFADDR = 0x00;  /*Give address 0x00*/
    id = REG_NFDATA;  /*First byte, Maker code: 0xEC->Samsung*/
    id = (id << 8) | REG_NFDATA; /*Second byte, Device ID:0xDA->K9F2G08*/
    /*We can read the followed 3 bytes(0x10,0x95,0x44) here, but it's useless.*/
    nand_deselect();
    return id;
}
#define TACLS       1    // 1-clk
#define TWRPH0      4    // 4-clk
#define TWRPH1      1    // 1-clk  //TACLS+TWRPH0+TWRPH1>=50ns
/**
 * nand_init - Initial the Nandflash controller and nand flash information structure "nand"
 * @nand:       The nand flash information
 * Return:      0->success <0 failed
 */
int nand_init(struct boot_nand_t *nand)
{
    int i, ret = -1;
    unsigned short nand_id;
    /*TACL=1, TWRPH0=4, TWRPH1=1, bit[0]=0 means the Nandflash bit witdth is 8bit(K9F2G08 is 8bit)*/
    REG_NFCONF= (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);
    /*
     * Bit[13:12]  No lock
     * Bit[10:8]   No nandflash interrupt
     * Bit[6:4]    Initialize ECC and lock data area & spare area ECC
     * Bit[1]      Enable nand flash chip select
     * Bit[0]      Enable nand flash controller
     */
    REG_NFCONT= (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
    for (i=0; i<10; i++) ;  /*Wait tWB(100ns)*/
    nand_id = nand_read_id();
    /*K9F2G08 page/read/write size is 2K bytes, spare size is 64 bytes
     * and block/erase size is 128K*/
    if ( NAND_K9F2G08 == nand_id )  /* Samsung K9F2G08 */
    {
        /*1 Device = 2048 Blocks, 1 Block=64Pages, 1 Pages=(2K Bytes data+ 64Bytes spare)*/
        nand->id = NAND_K9F2G08;
        nand->spare_size = 64;    /* 64 bytes */
        nand->page_size = 0x0800;    /* 1<<11=2K */
        nand->block_size = 0x20000;  /* 1<<17=128K*/
        nand->block_num = 2048;      /* 1<<17=128K*/
        /*Bad block tag is the first byte in spare area*/
        nand->bad_block_offset = nand->page_size;
        ret = 0;
    }
    return ret;
}
/**
 * nand_read_page - Read the data from a page main data area
 * @nand:       The nand flash information
 * @page_num:   The read page number
 * @offset:     The read data start offset address in the page
 * @size:       The request read data length
 * @data:       The read data  output buffer
 * Return:      >=0 read bytes
 */
int nand_read_page(struct boot_nand_t *nand, ulong page_num, ulong offset, char *data, ulong size)
{
    uchar  *ptr = (uchar *)data;
    ulong  i, bytes;
    /*Avoid the offset+size larger than a page size(include main data and spare data size) */
    bytes = ((nand->page_size+nand->spare_size-offset)>=size ? size : (nand->page_size+nand->spare_size)-offset);
    nand_select();
    nand_clear_RnB();
    REG_NFCMD = NAND_CMD_READ0;
    /* Write Address */
    REG_NFADDR = 0;
    REG_NFADDR = 0;
    REG_NFADDR = page_num & 0xff;
    REG_NFADDR = (page_num >> 8) & 0xff;
    REG_NFADDR = (page_num >> 16) & 0xff;
    REG_NFCMD = NAND_CMD_READSTART;
    /*
     * After give NAND_CMD_READSTART command, when the RnB get a rising edge signal, it
     * will set(Read S3C2440 datasheet about NFCONT register) the NFSTAT register bit[2]
     * in nandflash controller. After get this signal, then we can read the data or send
     * followed command
     */
    nand_detect_RnB();
    /* If the offset address in the page is 0 and need read a whole page,
     * then we read the whole page, or use the random page read */
    if(0==offset && nand->page_size==size)
            goto START_READ;
    /*Page Random Read will come here*/
    REG_NFCMD = NAND_CMD_RNDOUT;
    REG_NFADDR = offset & 0xff;
    REG_NFADDR = (offset >> 8) & 0xff;
    REG_NFCMD = NAND_CMD_RNDOUTSTART;
START_READ:
    for(i=0; i<bytes; i++)
    {
       *ptr = REG_NFDATA;
        ptr++;
    }
    nand_deselect();
    return bytes;
}
/**
 * nand_write_page - Write the data to a page main data area
 * @nand:       The nand flash information
 * @page_num:   The written page number
 * @offset:     The written data start offset address in the page
 * @size:       The written data length
 * @data:       The written data
 * Return:      >=0 write bytes
 */
int nand_write_page(struct boot_nand_t *nand, ulong page_num, ulong offset, char *data, ulong size)
{
    uchar  *ptr8 = (uchar *)data;
    uchar  stat;
    int    ret;
    ulong  i, bytes;
    /*Avoid the offset+size larger than a page size(include main data and spare data size) */
    bytes = ((nand->page_size+nand->spare_size-offset)>size ? size : (nand->page_size+nand->spare_size)-offset);
    nand_select();
    nand_clear_RnB();
    REG_NFCMD = NAND_CMD_SEQIN;
    /* Write Address */
    REG_NFADDR = 0;
    REG_NFADDR = 0;
    REG_NFADDR = page_num & 0xff;
    REG_NFADDR = (page_num >> 8) & 0xff;
    REG_NFADDR = (page_num >> 16) & 0xff;
    /* If the offset address in the page is 0 and need write a whole page data,
     * then we read the whole page, or use the random page program */
    if(0==offset && nand->page_size==size)
            goto START_PROG;
    /*Random page program will come here*/
    REG_NFCMD = NAND_CMD_RNDIN;
    REG_NFADDR = offset & 0xff;
    REG_NFADDR = (offset >> 8) & 0xff;
START_PROG:
    for(i=0; i<bytes; i++)
    {
        REG_NFDATA = *ptr8;
        ptr8++;
    }
    REG_NFCMD = NAND_CMD_PAGEPROG;
    /*
     * After give NAND_CMD_PAGEPROG command, when the RnB get a rising edge signal, it
     * will set(Read S3C2440 datasheet about NFCONT register) the NFSTAT register bit[2]
     * in nandflash controller. After get this signal, then we can send followed command.
     */
    nand_detect_RnB();
    /* When program operation is completed, the Write Status register Bit[I/O] 0 maybe checked,
     * bit[0]=0 means pass, or bit[0]=1 means Fail. Refer the top table definition  */
    REG_NFCMD = NAND_CMD_STATUS;
    stat = REG_NFDATA;
    if(stat & 0x01)
    {
        dbg_print("Random Program page number @%lu failure\n", page_num);
        ret = -1; /*Program failure*/
    }
    else
    {
        ret = bytes;
    }
    nand_deselect();
    return ret;
}
/**
 * is_bad_block - check the block which the "addr" in is valid or not
 * @nand:  Nandflash information
 * @addr:  The offset address in whole nandflash, no need block alignment
 * Return: 1->bad block, 0->Valid block
 */
int is_bad_block(struct boot_nand_t *nand, ulong addr)
{
    char data;
    ulong page_num;
    ulong block_start;
    int  page_shift = generic_ffs(nand->page_size)-1;
    /*Get start address of the block wherre the "addr" in*/
    block_start = addr & (~(nand->block_size-1));
    /* Get the first page number in the block, the Bad Block Tag is set in
     * the first bit in the first page spare area in the block */
    page_num = block_start >> page_shift;
    nand_read_page(nand, page_num, nand->bad_block_offset, &data, 1);
    if (data != 0xff)
    {
        printf("Bad Block @%08lx by address @%08lx\n",block_start, addr);
        nand_deselect();
        return 1;
    }
    nand_deselect();
    return 0;
}
/**
 * mark_bad_block - Mark the block as bad block
 * @nand:  Nandflash information
 * @addr:  The offset address in whole nandflash, no need block alignment
 * Return: 0->mark bad block success, <0 mark bad block failed.
 */
int mark_bad_block(struct boot_nand_t *nand, ulong addr)
{
    char data = 0xEE;
    ulong page_num;
    ulong block_num;
    ulong block_start;
    int  ret;
    /*Get start address of the block wherre the "addr" in*/
    block_start = addr & (~(nand->block_size-1));
    /* Get the first page number in the block, the Bad Block Tag is set in
     * the first bit in the first page spare area in the block */
    page_num = block_start >> (generic_ffs(nand->page_size)-1);
    ret = nand_write_page(nand, page_num, nand->bad_block_offset, &data, 1);
    ret = ret<0 ? ret: 0;
    block_num = block_start >> (generic_ffs(nand->block_size)-1);
    dbg_print("Mark  bad block index [$%lu] address @0x%08lx %s.\n",
                    block_num, block_start, ret==0?"success":"failed");
    return ret;
}
/**
 * nand_erase_block - Erase a block specify by the block_num
 * @nand:       Nandflash information
 * @block_num:  The erase block index number
 * Return:      0->success, <0  Failure
 */
int nand_erase_block(struct boot_nand_t *nand, ulong block_num)
{
    uchar   stat;
    int     ret = 0;
    ulong   block_start; /*Block start address*/
    nand_select();
    nand_clear_RnB();
    REG_NFCMD = NAND_CMD_ERASE1;
    REG_NFADDR = (block_num<<6) & 0xff;     /*Row address A18~A19*/
    REG_NFADDR = (block_num>>2) & 0xff;     /*Row address A20~A27*/
    REG_NFADDR = (block_num>>10) & 0x0f;    /*Row address A28*/
    REG_NFCMD = NAND_CMD_ERASE2;
   /*
    * After give NAND_CMD_ERASE2 command, when the RnB get a rising edge signal, it
    * will set(Read S3C2440 datasheet about NFCONT register) the NFSTAT register bit[2]
    * in nandflash controller. After get this signal, then we can send next command.
    */
    nand_detect_RnB();
   /* When erase operation is completed, the Write Status register Bit[I/O] 0 maybe checked,
    * bit[0]=0 means pass, or bit[0]=1 means Fail. Refer the top table definition  */
    REG_NFCMD = NAND_CMD_STATUS;
    stat = REG_NFDATA;
    block_start = block_num<<(generic_ffs(nand->block_size)-1);
    if( stat&(1<<0) )
    {
         printf("Erase block index [$%lu] address @0x%08lx failed.\n", block_num, block_start);
         mark_bad_block(nand, block_start);
         ret = -1;
         goto OUT;
    }
    dbg_print("Erase block index [$%lu] address @0x%08lx success.\n", block_num, block_start);
OUT:
    nand_deselect();
    return ret;
}
/**
 * nand_erase - Erase some blocks from start_addr
 * @nand:        Nandflash information
 * @start_addr:  The erase start address, it must be aligment
 * @size:        The erase block size, it must be  n*block_size
 * @skip_bad:    Whether need auto skip the bad block or not, if skip, the erase size don't change
 * Return:       0->success, >0 Bad block count
 */
int nand_erase(struct boot_nand_t *nand, ulong start_addr, ulong size, int skip_bad)
{
    int     block_num, ret=0;
    int     failed = 0;
    ulong   addr;
    int     block_shift = generic_ffs(nand->block_size)-1;
    if ( (start_addr & (nand->block_size-1)) || (size & (nand->block_size-1)) )
    {
        printf("nand erase address @0x%08lx or size $%lu not block aligment.\n", start_addr, size);
        return -1;       /* invalid alignment */
    }
    addr = start_addr;
    while( addr<(start_addr+size) )
    {
        block_num = addr>> block_shift;
        ret = nand_erase_block(nand, block_num);
        if(ret < 0)
        {
            if(skip_bad)
            {
                /*Erase next block*/
                addr += nand->block_size;
                size += nand->block_size;
                continue;
            }
            else
            {
                failed ++;
            }
        }
        else
            addr += nand->block_size;
    }
    /*If don't skip the bad block, then return the erase block failure times, or return OK.*/
    ret = (!skip_bad && failed) ? failed :  0;
    return ret;
}
/*
 * nand_scrub - nand erase the whole Nandflash
 * @nand:       The nand flash information
 */
void nand_scrub(struct boot_nand_t *nand)
{
    int i;
    for(i=0; i<nand->block_num; i++)
       nand_erase_block(nand, i);
}
/* nand_read_spare - Read some bytes from the spare first byte
 * @nand:       The nand flash information
 * @page_addr:  The page address in the whole Nand flash, no need page alignment
 * @size:       The spare area request read size, which start from the spare first byte
 * @buf:        The output data buffer
 * Return:      Read spare area data bytes
 */
int nand_read_spare(struct boot_nand_t *nand, ulong page_addr, int size, char *buf)
{
    ulong page_num;
    ulong bytes;
    int  page_shift = generic_ffs(nand->page_size)-1;
    size = size > nand->spare_size ? nand->spare_size : size;
    page_num = page_addr >> page_shift;   /*The page number in the whole Nandflash*/
    bytes = nand_read_page(nand, page_num, nand->bad_block_offset, buf, size);
    return bytes;
}
/* nand_write_spare - Write some bytes to the spare first byte
 * @nand:       The nand flash information
 * @page_addr:  The page address in the whole Nand flash, no need page alignment
 * @size:       The write data size
 * @buf:        The write data
 * Return:      Write to spare area data bytes
 */
int nand_write_spare(struct boot_nand_t *nand, ulong page_addr, int size, char *buf)
{
    ulong page_num;
    ulong bytes;
    int  page_shift = generic_ffs(nand->page_size)-1;
    size = size > nand->spare_size ? nand->spare_size : size;
    page_num = page_addr >> page_shift;   /*The page number in the whole Nandflash*/
    bytes = nand_write_page(nand, page_num, nand->bad_block_offset, buf, size);
    return bytes;
}
/**
 * nand_read -   Read some datas in the main data area in the page
 * @nand:        Nandflash information
 * @start_addr:  The read start address, it must be page alignment
 * @size:        The request read data size, no need alignment
 * @buf:         The read data output buffer
 * Return:       >=0 Read data bytes,  <0 Read failure
 */
int nand_read(struct boot_nand_t *nand, ulong start_addr, ulong size, char *buf)
{
    ulong addr;
    ulong page_num;
    ulong page_offset;
    ulong page_mask = nand->page_size-1;
    ulong bytes = 0;
    ulong left;
    int  page_shift = generic_ffs(nand->page_size)-1;
    left = size;
    addr = start_addr;
    /* The address must be page alignment*/
    if( (addr & page_mask) )
    {
          printf("nand read address @0x%08lx not alignment.\n", addr);
          return -1;
    }
    while(left > 0)
    {
         /*If the addr is block alignment, then we check this block is valid or not*/
         if ( ((addr&(nand->block_size-1))==0) && is_bad_block(nand, addr) )
         {
                /*Skip Bad block and goto next block */
                dbg_print("Skip bad block @0x%08lx\n", addr);
                addr += nand->block_size;
                continue;
         }
         page_num = addr >> page_shift;   /*The page number in the whole Nandflash*/
         page_offset = addr & page_mask;     /*The offset address in the page*/
         if( left >= nand->page_size)
         {
             bytes = nand_read_page(nand, page_num, page_offset, buf, nand->page_size);
#if 1
             dbg_print("Read whole page: addr=%08lx page_num=%d page_offset=%08lx, bytes=%lu \n",
                             addr, page_num, page_offset, bytes);
#endif
         }
         else
         {
             bytes = nand_read_page(nand, page_num, page_offset, buf, size%nand->page_size);
#if 1
             printf("Read part page: addr=%08lx page_num=%d page_offset=%d, bytes=%lu \n",
                             addr, page_num, page_offset, size%nand->page_size);
#endif
         }
         addr+=bytes;
         buf += bytes;
         left-=bytes;
    }
    return bytes;
}
/**
 * nand_write -  Write some datas to the main data area in the page
 * @nand:        Nandflash information
 * @start_addr:  The write start address, it must be page alignment
 * @size:        The write data size, no need alignment
 * @buf:         The write data
 * Return:       >=0 Write data bytes,  <0 Write failure
 */
int nand_write(struct boot_nand_t *nand, ulong start_addr, ulong size, char *buf)
{
    ulong addr;
    ulong page_num;
    ulong page_offset;
    ulong page_mask = nand->page_size-1;
    ulong bytes = 0;
    ulong left;
    int  page_shift = generic_ffs(nand->page_size)-1;
    left = size;
    addr = start_addr;
    /* The address must be page alignment*/
    if( (addr & page_mask) )
    {
          printf("nand read address @0x%08lx not alignment.\n", addr);
          return -1;
    }
    while(left > 0)
    {
         /*If the addr is block alignment, then we check this block is valid or not*/
         if ( ((addr&(nand->block_size-1))==0) && is_bad_block(nand, addr) )
         {
                /*Skip Bad block and goto next block */
                dbg_print("Skip bad block @0x%08lx\n", addr);
                addr += nand->block_size;
                continue;
         }
         page_num = addr >> page_shift;   /*The page number in the whole Nandflash*/
         page_offset = addr & page_mask;     /*The offset address in the page*/
         if( left >= nand->page_size)
         {
             bytes = nand_write_page(nand, page_num, page_offset, buf, nand->page_size);
#if 1
             dbg_print("Write whole page: addr=%08lx page_num=%d page_offset=%08lx, bytes=%lu \n",
                             addr, page_num, page_offset, bytes);
#endif
         }
         else
         {
             bytes = nand_write_page(nand, page_num, page_offset, buf, size%nand->page_size);
#if 1
             dbg_print("Write part page: addr=%08lx page_num=%d page_offset=%d, bytes=%lu \n",
                             addr, page_num, page_offset, size%nand->page_size);
#endif
         }
         addr+=bytes;
         buf += bytes;
         left-=bytes;
    }
    return bytes;
}
#if 0
/**
 * nand_wait - wait Nandflash goes to Ready to operate
 */
static inline void nand_wait(void)
{
    int i;
    /*NFSTAG register bit[0] is RnB:  0->Nandflash Busy  1->Nandflash Ready to operate */
    while (!(REG_NFSTAT & NFSTAT_BUSY))  /*bit[0]*/
    {
        dbg_print("Nandflash is busy.\n");
        for (i = 0; i < 10; i++) ;
    }
}
/**
 * nand_reset - Reset the Nandflash
 */
static void nand_reset(void)
{
    nand_select(); /* chip Enable */
    nand_clear_RnB(); /*Clear Ready & Busy signal*/
    REG_NFCMD = NAND_CMD_RESET; /*Read ID command*/
    REG_NFADDR = 0x00;  /*Give address 0x00*/
    nand_detect_RnB();
    nand_deselect();
}
#endif
linux-bsp/asm-study/myboot/led_beep.c
New file
@@ -0,0 +1,56 @@
/********************************************************************************************
 *        File:  led_beep.c
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  LED & Beep operate funciton.
 *   ChangeLog:  1, Release initial version on "Tue Jul 12 16:43:18 CST 2011"
 *
 *******************************************************************************************/
#include <common.h>
#define DELAY_TIME   1000000
/*LED & Beep */
#define GPBCON   (*(unsigned long volatile *)0x56000010)
#define GPBDAT   (*(unsigned long volatile *)0x56000014)
#define GPBUP    (*(unsigned long volatile *)0x56000018)
inline void delay(unsigned long loops)
{
    __asm__ volatile ("1:\n" "subs %0, %1, #1\n" "bne 1b":"=r" (loops):"0"(loops));
}
void init_led_beep(void)
{
    /*  Set GPB5,GPB6,GPB8,GPB10 as GPIO mode(0x01) */
    GPBCON = (GPBCON | 0x333C03) & 0x111401;
    GPBUP = (GPBUP | 0x560);
    /* Set GPB5,GPB6,GPB8,GPB10 as high level, to turn LED0,LED1,LED2,LED3 off */
    GPBDAT = (GPBDAT | 0x560);
}
void turn_led_on(int led)
{
    GPBDAT = (GPBDAT & (~(1 << led)));
    delay(DELAY_TIME);
}
void turn_led_off(int led)
{
    /* Turn LED0 on */
    GPBDAT = (GPBDAT | (1 << led));
    delay(DELAY_TIME);
}
void beep(int count)
{
    int i;
    for (i = 0; i < count; i++)
    {
        GPBDAT |= 1 << BEEP;    /* Set Beep GPIO as high level */
        delay(DELAY_TIME * 50);
        GPBDAT &= ~(1 << BEEP); /* Set Beep GPIO as low level */
        delay(DELAY_TIME * 50);
    }
}
linux-bsp/asm-study/myboot/makefile
New file
@@ -0,0 +1,118 @@
# ***********************************************************************
# *        File:  makefile
# *     Version:  1.0.0
# *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
# * Description:  Makefile used to cross compile the ASM source code
# *   ChangeLog:  1, Release initial version on "Sun Mar 20 18:41:04 CST 2011"
# *
# ***********************************************************************
#
APP_NAME=bootstrap
#INST_PATH=/tftp
# Enable "printf" function for help, don't enable it for production to save about 2K size
CONFIG_PRINTF_DBG=y
# When wanna burn the image to nandflash and start from it, then commont follow option
RAM_DEBUG=y
BOARD=SMDK2440
#BOARD=SMDK2416
export BOARD
SRC_TOP=$(CURDIR)
CFLAGS+=-I${SRC_TOP}/include
CFLAGS+=-Os -D__KERNEL__ -DCONFIG_ARM -D__ARM__ -DBOARD_$(BOARD)
PLATFORM_LIBS += -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc
ifeq ($(BOARD),SMDK2440)
  PLATFORM_LIBS += -lc -L/opt/buildroot-2011.11/arm920t/usr/arm-unknown-linux-uclibcgnueabi/sysroot/usr/lib/
  ifeq ($(RAM_DEBUG),y)
       TEXT_BASE=0x33000000
  else
       TEXT_BASE=0x00000000
  endif
# Set the stack top base address here
CFLAGS+=-DTEXT_BASE=$(TEXT_BASE) -DSTACK_BASE=0x33000000
CROSS_COMPILE=/opt/xtools/arm920t/bin/arm-linux-
CFLAGS+= -fno-strict-aliasing  -fno-common -ffixed-r8 -msoft-float
CFLAGS+=-march=armv4t -Wall -Wstrict-prototypes -fno-stack-protector
endif
ifeq ($(BOARD),SMDK2416)
TEXT_BASE=0x33000000
CFLAGS+=-DTEXT_BASE=$(TEXT_BASE)
CROSS_COMPILE=/opt/buildroot-2011.11/arm926t/usr/bin/arm-linux-
CFLAGS+= -fno-strict-aliasing  -fno-common -ffixed-r8 -msoft-float -mfloat-abi=soft
CFLAGS+=-march=armv4t -Wstrict-prototypes -fno-stack-protector
endif
AS  = $(CROSS_COMPILE)as
LD  = $(CROSS_COMPILE)ld
CC  = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR  = $(CROSS_COMPILE)ar
NM  = $(CROSS_COMPILE)nm
LDR = $(CROSS_COMPILE)ldr
STRIP   = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
RANLIB  = $(CROSS_COMPILE)RANLIB
gccincdir := $(shell $(CC) -print-file-name=include)
CFLAGS += -ffreestanding -nostdinc -isystem $(gccincdir) -pipe
CFLAGS += -fno-builtin
LDFLAGS=-Bstatic -T$(APP_NAME).lds -Ttext $(TEXT_BASE)
AFLAGS := $(CFLAGS) -D__ASSEMBLY__
export  CROSS_COMPILE AS LD CC CPP AR NM STRIP OBJCOPY OBJDUMP CFLAGS
SOBJS   := start.o mem_init.o
OBJS    := bootstrap.o led_beep.o interrupt.o serial.o common.o xmodem.o k9f2g08.o
ifeq ($(CONFIG_PRINTF_DBG), y)
CFLAGS+=-DCONFIG_PRINTF_DBG
endif
ALL: .depend $(SOBJS) $(OBJS)
    cd $(SRC_TOP)
    ${LD} $(LDFLAGS) $(SOBJS) \
    --start-group $(OBJS) \
    --end-group $(PLATFORM_LIBS) \
    -Map $(APP_NAME).map  -o $(APP_NAME).elf
    ${OBJCOPY} -O binary $(APP_NAME).elf $(APP_NAME).bin
    @chmod 777 $(APP_NAME).bin
    @rm -f *.elf *.o
.depend:    makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
    $(CC) -M $(AFLAGS) -D__ASSEMBLY__ $(SOBJS:.o=.S) > $@
    $(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@
sinclude .depend
%.o: %.S
     $(CC) $(AFLAGS) -c -o $@ $<
%.o: %.c
     $(CC) $(CFLAGS) -c -o $@ $<
install: $(APP_NAME).bin
    cp $(APP_NAME).bin $(INST_PATH) -f
    cp $(APP_NAME).bin /tftp -f
clean:
    @find $(OBJTREE) -type f \
            \( -name 'core' -o -name '*.bak' -o -name '*~' -o -name .depend \
            -o -name '*.o'  -o -name '*.a' -o -name '*.elf' \) -print \
            | xargs rm -f
    @rm -f $(APP_NAME).bin
    @rm -f $(APP_NAME).map
distclean clear: clean
    @rm -f cscope.* tags
linux-bsp/asm-study/myboot/mem_init.S
New file
@@ -0,0 +1,170 @@
/*
 * Memory Setup stuff - taken from blob memsetup.S
 *
 * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and
 *                     Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
 *
 * Modified for the Samsung SMDK2410 by
 * (C) Copyright 2002
 * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>
 *
 * Modified for the friendly-arm SBC-2410X by
 * (C) Copyright 2005
 * JinHua Luo, GuangDong Linux Center, <luo.jinhua@gd-linux.com>
 *
 * 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
 */
/*
 * Taken from linux/arch/arm/boot/compressed/head-s3c2410.S
 *
 * Copyright (C) 2002 Samsung Electronics SW.LEE  <hitchcar@sec.samsung.com>
 */
#include <config.h>
#define BWSCON    0x48000000
/* BWSCON */
#define DW8            (0x0)
#define DW16            (0x1)
#define DW32            (0x2)
#define WAIT            (0x1<<2)
#define UBLB            (0x1<<3)
#define B1_BWSCON        (DW16)
#define B2_BWSCON        (DW16)
#define B3_BWSCON        (DW16 + WAIT + UBLB)
#define B4_BWSCON        (DW16)
#define B5_BWSCON        (DW16)
#define B6_BWSCON        (DW32)
#define B7_BWSCON        (DW32)
#define B0_Tacs            0x0
#define B0_Tcos            0x0
#define B0_Tacc            0x7
#define B0_Tcoh            0x0
#define B0_Tah            0x0
#define B0_Tacp            0x0
#define B0_PMC            0x0
#define B1_Tacs            0x0
#define B1_Tcos            0x0
#define B1_Tacc            0x7
#define B1_Tcoh            0x0
#define B1_Tah            0x0
#define B1_Tacp            0x0
#define B1_PMC            0x0
#define B2_Tacs            0x0
#define B2_Tcos            0x0
#define B2_Tacc            0x7
#define B2_Tcoh            0x0
#define B2_Tah            0x0
#define B2_Tacp            0x0
#define B2_PMC            0x0
#define B3_Tacs            0xc
#define B3_Tcos            0x7
#define B3_Tacc            0xf
#define B3_Tcoh            0x1
#define B3_Tah            0x0
#define B3_Tacp            0x0
#define B3_PMC            0x0
#define B4_Tacs            0x0
#define B4_Tcos            0x0
#define B4_Tacc            0x7
#define B4_Tcoh            0x0
#define B4_Tah            0x0
#define B4_Tacp            0x0
#define B4_PMC            0x0
#define B5_Tacs            0xc
#define B5_Tcos            0x7
#define B5_Tacc            0xf
#define B5_Tcoh            0x1
#define B5_Tah            0x0
#define B5_Tacp            0x0
#define B5_PMC            0x0
#define B6_MT            0x3    /* SDRAM */
#define B6_Trcd            0x1
#define B6_SCAN            0x1    /* 9bit */
#define B7_MT            0x3    /* SDRAM */
#define B7_Trcd            0x1    /* 3clk */
#define B7_SCAN            0x1    /* 9bit */
/* REFRESH parameter */
#define REFEN            0x1    /* Refresh enable */
#define TREFMD            0x0    /* CBR(CAS before RAS)/Auto refresh */
#define Trc            0x3    /* 7clk */
#define Tchr            0x2    /* 3clk */
#if defined(CONFIG_S3C2440)
#define Trp         0x2 /* 4clk */
#define REFCNT          1012
#else
#define Trp         0x0 /* 2clk */
#define REFCNT            0x0459
#endif
/**************************************/
_TEXT_BASE:
    .word    TEXT_BASE
.globl mem_init
mem_init:
    /* memory control configuration */
    /* make r0 relative the current location so that it */
    /* reads SMRDATA out of FLASH rather than memory ! */
    ldr     r0, =SMRDATA
    ldr r1, =mem_init
    sub    r0, r0, r1
    adr r3, mem_init       /* r3 <- current position of code   */
    add     r0, r0, r3
    ldr    r1, =BWSCON    /* Bus Width Status Controller */
    add     r2, r0, #13*4
0:
    ldr     r3, [r0], #4
    str     r3, [r1], #4
    cmp     r2, r0
    bne     0b
    /* everything is fine now */
    mov    pc, lr
    .ltorg
/* the literal pools origin */
SMRDATA:
    .word (0+(B1_BWSCON<<4)+(B2_BWSCON<<8)+(B3_BWSCON<<12)+(B4_BWSCON<<16)+(B5_BWSCON<<20)+(B6_BWSCON<<24)+(B7_BWSCON<<28))
    .word ((B0_Tacs<<13)+(B0_Tcos<<11)+(B0_Tacc<<8)+(B0_Tcoh<<6)+(B0_Tah<<4)+(B0_Tacp<<2)+(B0_PMC))
    .word ((B1_Tacs<<13)+(B1_Tcos<<11)+(B1_Tacc<<8)+(B1_Tcoh<<6)+(B1_Tah<<4)+(B1_Tacp<<2)+(B1_PMC))
    .word ((B2_Tacs<<13)+(B2_Tcos<<11)+(B2_Tacc<<8)+(B2_Tcoh<<6)+(B2_Tah<<4)+(B2_Tacp<<2)+(B2_PMC))
    .word ((B3_Tacs<<13)+(B3_Tcos<<11)+(B3_Tacc<<8)+(B3_Tcoh<<6)+(B3_Tah<<4)+(B3_Tacp<<2)+(B3_PMC))
    .word ((B4_Tacs<<13)+(B4_Tcos<<11)+(B4_Tacc<<8)+(B4_Tcoh<<6)+(B4_Tah<<4)+(B4_Tacp<<2)+(B4_PMC))
    .word ((B5_Tacs<<13)+(B5_Tcos<<11)+(B5_Tacc<<8)+(B5_Tcoh<<6)+(B5_Tah<<4)+(B5_Tacp<<2)+(B5_PMC))
    .word ((B6_MT<<15)+(B6_Trcd<<2)+(B6_SCAN))
    .word ((B7_MT<<15)+(B7_Trcd<<2)+(B7_SCAN))
    .word ((REFEN<<23)+(TREFMD<<22)+(Trp<<20)+(Trc<<18)+(Tchr<<16)+REFCNT)
    .word 0xb2
    .word 0x30
    .word 0x30
linux-bsp/asm-study/myboot/nand.h
New file
@@ -0,0 +1,271 @@
/*
 *  linux/include/linux/mtd/nand.h
 *
 *  Copyright (c) 2000 David Woodhouse <dwmw2@infradead.org>
 *                     Steven J. Hill <sjhill@realitydiluted.com>
 *               Thomas Gleixner <tglx@linutronix.de>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * Info:
 *    Contains standard defines and IDs for NAND flash devices
 *
 * Changelog:
 *    See git changelog.
 */
#ifndef __LINUX_MTD_NAND_H
#define __LINUX_MTD_NAND_H
#include <common.h>
#include <linux/bitops.h>
#define NAND_K9F2G08      0xecda
/* This constant declares the max. oobsize / page, which
 * is supported now. If you add a chip with bigger oobsize/page
 * adjust this accordingly.
 */
#define NAND_MAX_OOBSIZE    218
#define NAND_MAX_PAGESIZE    4096
/*
 * Constants for hardware specific CLE/ALE/NCE function
 *
 * These are bits which can be or'ed to set/clear multiple
 * bits in one go.
 */
/* Select the chip by setting nCE to low */
#define NAND_NCE        0x01
/* Select the command latch by setting CLE to high */
#define NAND_CLE        0x02
/* Select the address latch by setting ALE to high */
#define NAND_ALE        0x04
#define NAND_CTRL_CLE        (NAND_NCE | NAND_CLE)
#define NAND_CTRL_ALE        (NAND_NCE | NAND_ALE)
#define NAND_CTRL_CHANGE    0x80
/*
 * Standard NAND flash commands
 */
#define NAND_CMD_READ0        0x00        /*Page read period 1*/
#define NAND_CMD_READSTART    0x30        /*Page read period 2, for large page*/
#define NAND_CMD_READID        0x90        /*Read production ID*/
#define NAND_CMD_SEQIN        0x80        /*Page write period 1*/
#define NAND_CMD_PAGEPROG    0x10        /*Page write period 2*/
#define NAND_CMD_ERASE1        0x60        /*Block erase period 1*/
#define NAND_CMD_ERASE2        0xd0        /*Block erase period 2*/
#define NAND_CMD_STATUS        0x70        /*Read status command*/
#define NAND_CMD_RESET        0xff        /*Nandflash reset command*/
#define NAND_CMD_READ1        1
#define NAND_CMD_RNDOUT        0x05        /*Page random read period 1*/
#define NAND_CMD_RNDOUTSTART    0xE0    /*Page random read period 2*/
#define NAND_CMD_RNDIN        0x85        /*Page random write*/
#define NAND_CMD_READOOB    0x50
#define NAND_CMD_STATUS_MULTI    0x71
/* Extended commands for large page devices */
#define NAND_CMD_CACHEDPROG    0x15
/* Extended commands for AG-AND device */
/*
 * Note: the command for NAND_CMD_DEPLETE1 is really 0x00 but
 *       there is no way to distinguish that from NAND_CMD_READ0
 *       until the remaining sequence of commands has been completed
 *       so add a high order bit and mask it off in the command.
 */
#define NAND_CMD_DEPLETE1    0x100
#define NAND_CMD_DEPLETE2    0x38
#define NAND_CMD_STATUS_MULTI    0x71
#define NAND_CMD_STATUS_ERROR    0x72
/* multi-bank error status (banks 0-3) */
#define NAND_CMD_STATUS_ERROR0    0x73
#define NAND_CMD_STATUS_ERROR1    0x74
#define NAND_CMD_STATUS_ERROR2    0x75
#define NAND_CMD_STATUS_ERROR3    0x76
#define NAND_CMD_STATUS_RESET    0x7f
#define NAND_CMD_STATUS_CLEAR    0xff
#define NAND_CMD_NONE        -1
/* Status bits */
#define NAND_STATUS_FAIL    0x01
#define NAND_STATUS_FAIL_N1    0x02
#define NAND_STATUS_TRUE_READY    0x20
#define NAND_STATUS_READY    0x40
#define NAND_STATUS_WP        0x80
/*
 * Constants for ECC_MODES
 */
typedef enum
{
    NAND_ECC_NONE,
    NAND_ECC_SOFT,
    NAND_ECC_HW,
    NAND_ECC_HW_SYNDROME,
    NAND_ECC_HW_OOB_FIRST,
} nand_ecc_modes_t;
/*
 * Constants for Hardware ECC
 */
/* Reset Hardware ECC for read */
#define NAND_ECC_READ        0
/* Reset Hardware ECC for write */
#define NAND_ECC_WRITE        1
/* Enable Hardware ECC before syndrom is read back from flash */
#define NAND_ECC_READSYN    2
/* Bit mask for flags passed to do_nand_read_ecc */
#define NAND_GET_DEVICE        0x80
/* Option constants for bizarre disfunctionality and real
*  features
*/
/* Chip can not auto increment pages */
#define NAND_NO_AUTOINCR    0x00000001
/* Buswitdh is 16 bit */
#define NAND_BUSWIDTH_16    0x00000002
/* Device supports partial programming without padding */
#define NAND_NO_PADDING        0x00000004
/* Chip has cache program function */
#define NAND_CACHEPRG        0x00000008
/* Chip has copy back function */
#define NAND_COPYBACK        0x00000010
/* AND Chip which has 4 banks and a confusing page / block
 * assignment. See Renesas datasheet for further information */
#define NAND_IS_AND        0x00000020
/* Chip has a array of 4 pages which can be read without
 * additional ready /busy waits */
#define NAND_4PAGE_ARRAY    0x00000040
/* Chip requires that BBT is periodically rewritten to prevent
 * bits from adjacent blocks from 'leaking' in altering data.
 * This happens with the Renesas AG-AND chips, possibly others.  */
#define BBT_AUTO_REFRESH    0x00000080
/* Chip does not require ready check on read. True
 * for all large page devices, as they do not support
 * autoincrement.*/
#define NAND_NO_READRDY        0x00000100
/* Chip does not allow subpage writes */
#define NAND_NO_SUBPAGE_WRITE    0x00000200
/* Options valid for Samsung large page devices */
#define NAND_SAMSUNG_LP_OPTIONS \
    (NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK)
/* Macros to identify the above */
#define NAND_CANAUTOINCR(chip) (!(chip->options & NAND_NO_AUTOINCR))
#define NAND_MUST_PAD(chip) (!(chip->options & NAND_NO_PADDING))
#define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG))
#define NAND_HAS_COPYBACK(chip) ((chip->options & NAND_COPYBACK))
/* Large page NAND with SOFT_ECC should support subpage reads */
#define NAND_SUBPAGE_READ(chip) ((chip->ecc.mode == NAND_ECC_SOFT) \
                    && (chip->page_shift > 9))
/* Mask to zero out the chip options, which come from the id table */
#define NAND_CHIPOPTIONS_MSK    (0x0000ffff & ~NAND_NO_AUTOINCR)
/* Non chip related options */
/* Use a flash based bad block table. This option is passed to the
 * default bad block table function. */
#define NAND_USE_FLASH_BBT    0x00010000
/* This option skips the bbt scan during initialization. */
#define NAND_SKIP_BBTSCAN    0x00020000
/* This option is defined if the board driver allocates its own buffers
   (e.g. because it needs them DMA-coherent */
#define NAND_OWN_BUFFERS    0x00040000
/* Options set by nand scan */
/* bbt has already been read */
#define NAND_BBT_SCANNED    0x40000000
/* Nand scan has allocated controller struct */
#define NAND_CONTROLLER_ALLOC    0x80000000
/* Cell info constants */
#define NAND_CI_CHIPNR_MSK    0x03
#define NAND_CI_CELLTYPE_MSK    0x0C
/*
 * NAND Flash Manufacturer ID Codes
 */
#define NAND_MFR_TOSHIBA    0x98
#define NAND_MFR_SAMSUNG    0xec
#define NAND_MFR_FUJITSU    0x04
#define NAND_MFR_NATIONAL    0x8f
#define NAND_MFR_RENESAS    0x07
#define NAND_MFR_STMICRO    0x20
#define NAND_MFR_HYNIX        0xad
#define NAND_MFR_MICRON        0x2c
#define NAND_MFR_AMD        0x01
/*
* Constants for oob configuration
*/
#define NAND_SMALL_BADBLOCK_POS        5
#define NAND_LARGE_BADBLOCK_POS        0
#if defined(CONFIG_S3C2410)
#define REG_NFCONF      __REGi(ELFIN_NAND_BASE + 0x0)
#define REG_NFCMD       __REGb(ELFIN_NAND_BASE + 0x4)
#define REG_NFADDR      __REGb(ELFIN_NAND_BASE + 0x8)
#define REG_NFDATA      __REGb(ELFIN_NAND_BASE + 0xc)
#define REG_NFSTAT      __REGb(ELFIN_NAND_BASE + 0x10)
#define NFSTAT_BUSY 1
#define nand_select()   (REG_NFCONF &= ~0x800)   /*Clear bit 11*/
#define nand_deselect() (REG_NFCONF |= 0x800)
#define nand_clear_RnB()    do {} while (0)
#define nand_detect_RnB()    do {} while (0)
#define nand_wait_RnB()    do {} while (0)
#elif defined(CONFIG_S3C2440) || defined(CONFIG_S3C2442)
#define REG_NFCONF      __REGi(ELFIN_NAND_BASE + 0x0)
#define REG_NFCONT      __REGi(ELFIN_NAND_BASE + 0x4)
#define REG_NFCMD       __REGb(ELFIN_NAND_BASE + 0x8)
#define REG_NFADDR      __REGb(ELFIN_NAND_BASE + 0xc)
#define REG_NFDATA      __REGb(ELFIN_NAND_BASE + 0x10)
#define REG_NFDATA16    __REGw(ELFIN_NAND_BASE + 0x10)
#define REG_NFSTAT      __REGb(ELFIN_NAND_BASE + 0x20)
#define NFSTAT_BUSY 1
#define nand_select()   (REG_NFCONT &= ~(1 << 1))
#define nand_deselect() (REG_NFCONT |= (1 << 1))
#define nand_clear_RnB()    (REG_NFSTAT |= (1 << 2))
#define nand_detect_RnB()   {while(!(REG_NFSTAT&(1<<2)));}   /*Wait Read & Busy signal goto high(not busy)*/
#define nand_wait_RnB()   {while(!(REG_NFSTAT&(1<<0)));}   /*Wait nand flash not busy, wait bit[0] goes to 1*/
#endif
#define SKIP_BAD_BLOCK       1
#define NOT_SKIP_BAD_BLOCK   0
struct boot_nand_t
{
    int page_size;
    int spare_size;
    int block_size;
    int block_num;
    int bad_block_offset;
    int id;
    //  unsigned long size;
};
int nand_init(struct boot_nand_t *nand);
int nand_read_page(struct boot_nand_t *nand, ulong page_num, ulong offset, char *data, ulong size);
int nand_write_page(struct boot_nand_t *nand, ulong page_num, ulong offset, char *data, ulong size);
int is_bad_block(struct boot_nand_t *nand, ulong addr);
int mark_bad_block(struct boot_nand_t *nand, ulong addr);
int nand_erase_block(struct boot_nand_t *nand, ulong block_num);
int nand_erase(struct boot_nand_t *nand, ulong start_addr, ulong size, int skip_bad);
void nand_scrub(struct boot_nand_t *nand);
int nand_read_spare(struct boot_nand_t *nand, ulong page_addr, int size, char *buf);
int nand_write_spare(struct boot_nand_t *nand, ulong page_addr, int size, char *buf);
int nand_read(struct boot_nand_t *nand, ulong start_addr, ulong size, char *buf);
int nand_write(struct boot_nand_t *nand, ulong start_addr, ulong size, char *buf);
#endif                          /* __LINUX_MTD_NAND_H */
linux-bsp/asm-study/myboot/rsa.c
New file
@@ -0,0 +1,602 @@
/*
 *  The RSA PK cryptosystem
 *
 *  Copyright (C) 2006  Christophe Devine
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License, version 2.1 as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *  MA  02110-1301  USA
 */
/*
 *  RSA was designed by Ron Rivest, Adi Shamir and Len Adleman.
 *
 *  http://theory.lcs.mit.edu/~rivest/rsapaper.pdf
 *  http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf
 */
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE 1
#endif
#include <common.h>
#include <rsa.h>
#if !defined(NO_GENPRIME)
/*
 * Generate an RSA keypair
 */
int rsa_gen_key( rsa_context *ctx, int nbits, int exponent,
                 int (*rng_f)(void *), void *rng_d )
{
    int ret;
    mpi P1, Q1, H, G;
    if( nbits < 128 || exponent < 3 || rng_f == NULL )
        return( ERR_RSA_BAD_INPUT_DATA );
    mpi_init( &P1, &Q1, &H, &G, NULL );
    memset( ctx, 0, sizeof( rsa_context ) );
    /*
     * find primes P and Q with Q < P so that:
     * GCD( E, (P-1)*(Q-1) ) == 1
     */
    CHK( mpi_lset( &ctx->E, exponent ) );
    nbits >>= 1;
    do
    {
        CHK( mpi_gen_prime( &ctx->P, nbits, 0, rng_f, rng_d ) );
        CHK( mpi_gen_prime( &ctx->Q, nbits, 0, rng_f, rng_d ) );
        if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 )
            mpi_swap( &ctx->P, &ctx->Q );
        if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 )
            continue;
        CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) );
        CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
        CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
        CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
        CHK( mpi_gcd( &G, &ctx->E, &H  ) );
    }
    while( mpi_cmp_int( &G, 1 ) != 0 );
    /*
     * D  = E^-1 mod ((P-1)*(Q-1))
     * DP = D mod (P - 1)
     * DQ = D mod (Q - 1)
     * QP = Q^-1 mod P
     */
    CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H  ) );
    CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) );
    CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) );
    CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) );
    ctx->len = ( mpi_size( &ctx->N ) + 7 ) >> 3;
cleanup:
    mpi_free( &P1, &Q1, &H, &G, NULL );
    if( ret != 0 )
    {
        rsa_free( ctx );
        return( ERR_RSA_KEY_GEN_FAILED | ret );
    }
    return( 0 );
}
#endif
/*
 * Perform an RSA public key operation
 */
int rsa_public( rsa_context   *ctx,
                unsigned char *input,  int ilen,
                unsigned char *output, int *olen )
{
    int ret;
    mpi T;
   // if( ilen != ctx->len || olen != ctx->len )
   //    return( ERR_RSA_BAD_INPUT_DATA );
    mpi_init( &T, NULL );
    CHK( mpi_import( &T, input, ilen ) );
    if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
    {
        mpi_free( &T, NULL );
        return( ERR_RSA_BAD_INPUT_DATA );
    }
    CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) );
    CHK( mpi_export( &T, output, olen ) );
cleanup:
    mpi_free( &T, NULL );
    if( ret != 0 )
        return( ERR_RSA_PUBLIC_FAILED | ret );
    return( 0 );
}
/*
 * Perform an RSA private key operation
 */
int rsa_private( rsa_context   *ctx,
                 unsigned char *input,  int ilen,
                 unsigned char *output, int *olen )
{
    int ret;
    mpi T, T1, T2;
   //if( ilen != ctx->len || olen != ctx->len )
   //    return( ERR_RSA_BAD_INPUT_DATA );
    mpi_init( &T, &T1, &T2, NULL );
    CHK( mpi_import( &T, input, ilen ) );
    if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 )
    {
        mpi_free( &T, NULL );
        return( ERR_RSA_BAD_INPUT_DATA );
    }
#if 0
    CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) );
#else
    /*
     * faster decryption using the CRT
     *
     * T1 = input ^ dP mod P
     * T2 = input ^ dQ mod Q
     */
    CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) );
    CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) );
    /*
     * T = (T1 - T2) * (Q^-1 mod P) mod P
     */
    CHK( mpi_sub_mpi( &T, &T1, &T2 ) );
    CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) );
    CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) );
    /*
     * output = T2 + T * Q
     */
    CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) );
    CHK( mpi_add_mpi( &T, &T2, &T1 ) );
#endif
    CHK( mpi_export( &T, output, olen ) );
cleanup:
    mpi_free( &T, &T1, &T2, NULL );
    if( ret != 0 )
        return( ERR_RSA_PRIVATE_FAILED | ret );
    return( 0 );
}
/*
 * Check if the public key is valid
 */
int rsa_check_pubkey( rsa_context *ctx )
{
    if( ( ctx->N.p[0] & 1 ) == 0 ||
        ( ctx->E.p[0] & 1 ) == 0 )
        return( ERR_RSA_KEY_CHK_FAILED );
    if( mpi_size( &ctx->N ) < 128 ||
        mpi_size( &ctx->N ) > 4096 )
        return( ERR_RSA_KEY_CHK_FAILED );
    if( mpi_size( &ctx->E ) < 2 ||
        mpi_size( &ctx->E ) > 64 )
        return( ERR_RSA_KEY_CHK_FAILED );
    return( 0 );
}
/*
 * Check if the private key is valid
 */
int rsa_check_privkey( rsa_context *ctx )
{
    int ret = 0;
    mpi TN, P1, Q1, H, G;
    mpi_init( &TN, &P1, &Q1, &H, &G, NULL );
    CHK( mpi_mul_mpi( &TN, &ctx->P, &ctx->Q ) );
    CHK( mpi_sub_int( &P1, &ctx->P, 1 ) );
    CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) );
    CHK( mpi_mul_mpi( &H, &P1, &Q1 ) );
    CHK( mpi_gcd( &G, &ctx->E, &H  ) );
    if( mpi_cmp_mpi( &TN, &ctx->N ) == 0 &&
        mpi_cmp_int( &G, 1 ) == 0 )
    {
        mpi_free( &TN, &P1, &Q1, &H, &G, NULL );
        return( 0 );
    }
cleanup:
    mpi_free( &TN, &P1, &Q1, &H, &G, NULL );
    return( ERR_RSA_KEY_CHK_FAILED | ret );
}
/*
 * Add the PKCS#1 v1.5 padding and do a public RSA
 */
int rsa_pkcs1_encrypt( rsa_context   *ctx,
                       unsigned char *input,  int ilen,
                       unsigned char *output, int *olen )
{
    int nb_pad;
    unsigned char *p = output;
    if( *olen != ctx->len || *olen < ilen + 11 )
    {
        return( ERR_RSA_BAD_INPUT_DATA );
    }
    nb_pad = *olen - 3 - ilen;
    *p++ = 0;
    *p++ = RSA_CRYPT;
    while( nb_pad-- > 0 )
    {
        do { *p = rand(); } while( *p == 0 );
        p++;
    }
    *p++ = 0;
    memcpy( p, input, ilen );
    return( rsa_public( ctx, output, *olen, output, olen ) );
}
/*
 * Do a private RSA, removes the PKCS#1 v1.5 padding
 */
int rsa_pkcs1_decrypt( rsa_context   *ctx,
                       unsigned char *input,  int  ilen,
                       unsigned char *output, int *olen )
{
    int ret;
    unsigned char *p, buf[512];
    if( ilen != ctx->len || ilen < 16 || ilen > 512 )
        return( ERR_RSA_BAD_INPUT_DATA );
    if( ( ret = rsa_private( ctx, input, ilen, buf, &ilen ) ) != 0 )
        return( ret );
    p = buf;
    if( *p++ != 0 || *p++ != RSA_CRYPT )
        return( ERR_RSA_INVALID_PADDING );
    while( *p != 0 )
    {
        if( p >= buf + ilen - 1 )
            return( ERR_RSA_INVALID_PADDING );
        p++;
    }
    p++;
    if( *olen < ilen - (int)(p - buf) )
        return( ERR_RSA_INVALID_PADDING );
    *olen = ilen - (int)(p - buf);
    memcpy( output, p, *olen );
    return( 0 );
}
/*
 * Perform a private RSA to sign a message digest
 */
int rsa_pkcs1_sign( rsa_context   *ctx,  int alg_id,
                    unsigned char *hash, int hashlen,
                    unsigned char *sig,  int siglen )
{
    int nb_pad;
    unsigned char *p = sig;
    if( siglen != ctx->len || siglen < 16 )
        return( ERR_RSA_BAD_INPUT_DATA );
    switch( alg_id )
    {
        case RSA_RAW:
            nb_pad = siglen - 3 - hashlen;
            break;
        case RSA_MD2:
        case RSA_MD4:
        case RSA_MD5:
            nb_pad = siglen - 3 - 34;
            break;
        case RSA_SHA1:
            nb_pad = siglen - 3 - 35;
            break;
        default:
            return( ERR_RSA_BAD_INPUT_DATA );
    }
    if( nb_pad < 8 )
        return( ERR_RSA_BAD_INPUT_DATA );
    *p++ = 0;
    *p++ = RSA_SIGN;
    memset( p, 0xFF, nb_pad );
    p += nb_pad;
    *p++ = 0;
    switch( alg_id )
    {
        case RSA_RAW:
            memcpy( p, hash, hashlen );
            break;
        case RSA_MD2:
            memcpy( p, ASN1_HASH_MDX, 18 );
            memcpy( p + 18, hash, 16 );
            p[13] = 2; break;
        case RSA_MD4:
            memcpy( p, ASN1_HASH_MDX, 18 );
            memcpy( p + 18, hash, 16 );
            p[13] = 4; break;
        case RSA_MD5:
            memcpy( p, ASN1_HASH_MDX, 18 );
            memcpy( p + 18, hash, 16 );
            p[13] = 5; break;
        case RSA_SHA1:
            memcpy( p, ASN1_HASH_SHA1, 15 );
            memcpy( p + 15, hash, 20 );
            break;
        default:
            return( ERR_RSA_BAD_INPUT_DATA );
    }
    return( rsa_private( ctx, sig, siglen, sig, &siglen ) );
}
/*
 * Perform a public RSA and check the message digest
 */
int rsa_pkcs1_verify( rsa_context   *ctx,  int alg_id,
                      unsigned char *hash, int hashlen,
                      unsigned char *sig,  int siglen )
{
    int ret, len;
    unsigned char *p, c, buf[512];
    if( siglen != ctx->len || siglen < 16 || siglen > 512 )
        return( ERR_RSA_BAD_INPUT_DATA );
    if( ( ret = rsa_public( ctx, sig, siglen, buf, &siglen ) ) != 0 )
        return( ret );
    p = buf;
    if( *p++ != 0 || *p++ != RSA_SIGN )
        return( ERR_RSA_INVALID_PADDING );
    while( *p != 0 )
    {
        if( p >= buf + siglen - 1 || *p != 0xFF )
            return( ERR_RSA_INVALID_PADDING );
        p++;
    }
    p++;
    len = siglen - (int)( p - buf );
    if( len == 34 )
    {
        c = p[13];
        p[13] = 0;
        if( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 )
            return( ERR_RSA_VERIFY_FAILED );
        if( ( c == 2 && alg_id == RSA_MD2 ) ||
            ( c == 4 && alg_id == RSA_MD4 ) ||
            ( c == 5 && alg_id == RSA_MD5 ) )
        {
            if( memcmp( p + 18, hash, 16 ) == 0 )
                return( 0 );
            else
                return( ERR_RSA_VERIFY_FAILED );
        }
    }
    if( len == 35 && alg_id == RSA_SHA1 )
    {
        if( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 &&
            memcmp( p + 15, hash, 20 ) == 0 )
            return( 0 );
        else
            return( ERR_RSA_VERIFY_FAILED );
    }
    if( len == hashlen && alg_id == RSA_RAW )
    {
        if( memcmp( p, hash, hashlen ) == 0 )
            return( 0 );
        else
            return( ERR_RSA_VERIFY_FAILED );
    }
    return( ERR_RSA_INVALID_PADDING );
}
/*
 * Free the components of an RSA key
 */
void rsa_free( rsa_context *ctx )
{
    mpi_free( &ctx->N,  &ctx->E,  &ctx->D,
              &ctx->P,  &ctx->Q,  &ctx->DP,
              &ctx->DQ, &ctx->QP, &ctx->RN,
              &ctx->RP, &ctx->RQ, NULL );
}
//#include "md5.h"
#define PTLEN   24
#define CTLEN  128
/*
 * Checkup routine
 */
int main ( void )
{
    int len;
    rsa_context rsa;
    unsigned char md5sum[16];
    unsigned char rsa_plaintext[PTLEN];
    unsigned char rsa_decrypted[PTLEN];
    unsigned char rsa_ciphertext[CTLEN];
    memset( &rsa, 0, sizeof( rsa ) );
    rsa.len = 128;
    mpi_read( &rsa.N , "9292758453063D803DD603D5E777D788" \
                       "8ED1D5BF35786190FA2F23EBC0848AEA" \
                       "DDA92CA6C3D80B32C4D109BE0F36D6AE" \
                       "7130B9CED7ACDF54CFC7555AC14EEBAB" \
                       "93A89813FBF3C4F8066D2D800F7C38A8" \
                       "1AE31942917403FF4946B0A83D3D3E05" \
                       "EE57C6F5F5606FB5D4BC6CD34EE0801A" \
                       "5E94BB77B07507233A0BC7BAC8F90F79", 16 );
    mpi_read( &rsa.E , "10001", 16 );
    mpi_read( &rsa.D , "24BF6185468786FDD303083D25E64EFC" \
                       "66CA472BC44D253102F8B4A9D3BFA750" \
                       "91386C0077937FE33FA3252D28855837" \
                       "AE1B484A8A9A45F7EE8C0C634F99E8CD" \
                       "DF79C5CE07EE72C7F123142198164234" \
                       "CABB724CF78B8173B9F880FC86322407" \
                       "AF1FEDFDDE2BEB674CA15F3E81A1521E" \
                       "071513A1E85B5DFA031F21ECAE91A34D", 16 );
    mpi_read( &rsa.P , "C36D0EB7FCD285223CFB5AABA5BDA3D8" \
                       "2C01CAD19EA484A87EA4377637E75500" \
                       "FCB2005C5C7DD6EC4AC023CDA285D796" \
                       "C3D9E75E1EFC42488BB4F1D13AC30A57", 16 );
    mpi_read( &rsa.Q , "C000DF51A7C77AE8D7C7370C1FF55B69" \
                       "E211C2B9E5DB1ED0BF61D0D9899620F4" \
                       "910E4168387E3C30AA1E00C339A79508" \
                       "8452DD96A9A5EA5D9DCA68DA636032AF", 16 );
    mpi_read( &rsa.DP, "C1ACF567564274FB07A0BBAD5D26E298" \
                       "3C94D22288ACD763FD8E5600ED4A702D" \
                       "F84198A5F06C2E72236AE490C93F07F8" \
                       "3CC559CD27BC2D1CA488811730BB5725", 16 );
    mpi_read( &rsa.DQ, "4959CBF6F8FEF750AEE6977C155579C7" \
                       "D8AAEA56749EA28623272E4F7D0592AF" \
                       "7C1F1313CAC9471B5C523BFE592F517B" \
                       "407A1BD76C164B93DA2D32A383E58357", 16 );
    mpi_read( &rsa.QP, "9AE7FBC99546432DF71896FC239EADAE" \
                       "F38D18D2B2F0E2DD275AA977E2BF4411" \
                       "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \
                       "A74206CEC169D74BF5A8C50D6F48EA08", 16 );
    printf( "  RSA key validation: " );
    if( rsa_check_pubkey(  &rsa ) != 0 ||
        rsa_check_privkey( &rsa ) != 0 )
    {
        printf( "failed\n" );
        return( 1 );
    }
    printf( "passed\n  PKCS#1 encryption : " );
    memcpy( rsa_plaintext,
        "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \
        "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD", PTLEN );
    len = CTLEN;
    if( rsa_pkcs1_encrypt( &rsa, rsa_plaintext,  PTLEN,
                                 rsa_ciphertext, &len ) != 0 )
    {
        printf( "failed\n" );
        return( 1 );
    }
    printf( "passed\n  PKCS#1 decryption : " );
    len = sizeof( rsa_decrypted );
    if( rsa_pkcs1_decrypt( &rsa, rsa_ciphertext, CTLEN,
                                 rsa_decrypted,  &len ) != 0 ||
        memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 )
    {
        printf( "failed\n" );
        return( 1 );
    }
    printf( "passed\n" );
#if 0
    md5_csum( rsa_plaintext, PTLEN, md5sum );
    if( rsa_pkcs1_sign( &rsa, RSA_MD5, md5sum, 16,
                        rsa_ciphertext, CTLEN ) != 0 )
    {
        printf( "failed\n" );
        return( 1 );
    }
    printf( "passed\n  PKCS#1 sig. verify: " );
    if( rsa_pkcs1_verify( &rsa, RSA_MD5, md5sum, 16,
                          rsa_ciphertext, CTLEN ) != 0 )
    {
        printf( "failed\n" );
        return( 1 );
    }
    printf( "passed\n\n" );
#endif
    rsa_free( &rsa );
    return( 0 );
}
linux-bsp/asm-study/myboot/serial.c
New file
@@ -0,0 +1,74 @@
/********************************************************************************************
 *        File:  serial.c
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  The UART on board drivers/functions.
 *   ChangeLog:  1, Release initial version on "Tue Jul 12 16:43:18 CST 2011"
 *
 *******************************************************************************************/
#include <common.h>
#define GPHCON   (*(unsigned long volatile *)0x56000070)
void serial_init(void)
{
    S3C24X0_UART *const uart = (S3C24X0_UART *) ELFIN_UART_BASE;
    /*Enable UART0,UART1,UART2 */
    GPHCON = 0x0000aaaa;
    /*Set Parity, Stopbit etc. */
    uart->ULCON &= 0XFFFFFF00;
    uart->ULCON |= 0X03;
    /*Disable modem */
    uart->UMCON = 0x0;
    /*Set UART FIFO control register */
    uart->UFCON = 0x00;
    uart->UCON = 0x805;         /*Enable FIFO */
    /*
     * UBRDIV = (UART Clock)/(baudrate*16) -1
     *        = (50 000 000)/(115200*16) -1
     *        = 26
     *        = 0x1A
     */
    uart->UBRDIV = 0x1A;
}
void serial_send_byte(char c)
{
    S3C24X0_UART *const uart = (S3C24X0_UART *) ELFIN_UART_BASE;
    /* wait for room in the tx FIFO */
    while (!(uart->UTRSTAT & 0x2)) ;
    uart->UTXH = c;
    if (c == '\n')              /* If \n, also do \r */
        serial_send_byte('\r');
}
int serial_is_recv_enable(void)
{
    S3C24X0_UART *const uart = (S3C24X0_UART *) ELFIN_UART_BASE;
    return uart->UTRSTAT & 0x1;
}
int serial_recv_byte(void)
{
    S3C24X0_UART *const uart = (S3C24X0_UART *) ELFIN_UART_BASE;
    /* wait for character to arrive */
    while (!(uart->UTRSTAT & 0x1)) ;
    return uart->URXH & 0xff;
}
void serial_puts(const char *s)
{
    while (*s)
    {
        serial_send_byte(*s++);
    }
}
linux-bsp/asm-study/myboot/start.S
New file
@@ -0,0 +1,348 @@
/********************************************************************************************
 *        File:  start.S - Startup Code for ARM920 CPU-core
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  When system power up, the CPU will comes here to excute the first code here.
 *   ChangeLog:  1, Release initial version on "Tue Jul 12 16:43:18 CST 2011"
 *
 *******************************************************************************************/
/*
 *************************************************************************
 *
 * Jump vector table as in table 3.1 in [1]
 *
 *************************************************************************
 */
#include <config.h>
.globl _start
_start:    b    start_code
    ldr    pc, _undefined_instruction
    ldr    pc, _software_interrupt
    ldr    pc, _prefetch_abort
    ldr    pc, _data_abort
    ldr    pc, _not_used
    ldr    pc, _irq
    ldr    pc, _fiq
_undefined_instruction:    .word undefined_instruction
_software_interrupt:    .word software_interrupt
_prefetch_abort:    .word prefetch_abort
_data_abort:        .word data_abort
_not_used:        .word not_used
_irq:            .word irq
_fiq:            .word fiq
    .balignl 16,0xdeadbeef
/*
 *************************************************************************
 *
 * Startup Code (called from the ARM reset exception vector)
 *
 * do important init only if we don't start from memory!
 * relocate armboot to ram
 * setup stack
 * jump to second stage
 *
 *************************************************************************
 */
_TEXT_BASE:
    .word    TEXT_BASE
.globl _armboot_start
_armboot_start:
    .word _start
/*
 * These are defined in the board-specific linker script.
 */
.globl _bss_start
_bss_start:
    .word __bss_start
.globl _bss_end
_bss_end:
    .word _end
/*
 * the actual start code
 */
start_code:
    /*
     * set the cpu to SVC32 mode
     */
    mrs    r0, cpsr
    bic    r0, r0, #0x1f
    orr    r0, r0, #0xd3
    msr    cpsr, r0
    /* Disable watchdog */
    ldr r0, =ELFIN_WATCHDOG_BASE
    mov r1, #0
    str r1, [r0]
    /* Disable Interrupt */
    ldr r0, =ELFIN_INTERRUPT_BASE
    mov r1, #0xffffffff
    str r1, [r0, #INTMSK_OFFSET]
    ldr r1, =0x000007ff
    str r1, [r0, #INTSUBMSK_OFFSET]
    /* flush v4 I/D caches */
    mov    r0, #0
    mcr    p15, 0, r0, c7, c7, 0    /* flush v3/v4 cache */
    mcr    p15, 0, r0, c8, c7, 0    /* flush v4 TLB */
    /* disable MMU stuff and caches */
    mrc    p15, 0, r0, c1, c0, 0
    bic    r0, r0, #0x00002300    @ clear bits 13, 9:8 (--V- --RS)
    bic    r0, r0, #0x00000087    @ clear bits 7, 2:0 (B--- -CAM)
    orr    r0, r0, #0x00000002    @ set bit 2 (A) Align
    orr    r0, r0, #0x00001000    @ set bit 12 (I) I-Cache
    mcr    p15, 0, r0, c1, c0, 0
 /*******************************************************************************************
  * Init system clock and power, FCLK:HCLK:PCLK = 1:4:8
  * Reference to S3C2440 datasheet: Chap 7 Clock&Power Management
  *
  * Initialize System Clock FCLK=400MHz HCLK=100MHz PCLK=50MHz
  * FCLK is used by ARM920T
  * HCLK is used for AHB bus, which is used by the ARM920T, the memory controller,
  *      the interrupt controller, the LCD controller, the DMA and USB host block.
  * PCLK is is used for APB bus,which is used by the peripherals such as WDT,IIS,I2C,
  *      PWM timer,MMC interface,ADC,UART,GPIO,RTC and SPI.
  ******************************************************************************************/
    /*Set LOCKTIME as default value 0x00ffffff*/
    ldr r0, =ELFIN_CLOCK_POWER_BASE
    ldr r1, =0x00ffffff
    str r1, [r0, #LOCKTIME_OFFSET]
 /*******************************************************************************************
  * Reference to S3C2440 datasheet: Chap 7-8 ~ Page 242
  *
  * Set the selection of Dividing Ratio between FCLK,HCLK and PCLK as FCLK:HCLK:PCLK = 1:4:8.
  * This ratio is determined by HDIVN(here is 2) and PDIVN(here is 1) control register.
  * Refer to the s3c2440 datasheet
  *******************************************************************************************/
    ldr r0, =ELFIN_CLOCK_POWER_BASE
    mov r1, #5
    str r1, [r0, #CLKDIVN_OFFSET]  /*Set Clock Divider*/
    mrc p15, 0, r1, c1, c0, 0
    orr r1, r1, #0xc0000000
    mcr p15, 0, r1, c1, c0, 0
 /***************************************************************************************
  *  Reference to S3C2440 datasheet: Chap 7-20 ~ Page 254
  *
  *  Set MPLLCON(0x4C000004) register as:
  *    [19:12]:  MDIV(Main Divider control)=0x7F (value set in MDIV_405)
  *      [9:4]:  PDIV(Pre-devider control)=0x02  (value set in PSDIV_405)
  *      [1:0]:  SDIV(Post divider control)=0x01 (value set in PSDIV_405)
  *
  *  MPLL(FCLK) = (2 * m * Fin)/(p * 2^s)
  *  m=(MDIV+8), p=(PDIV+2), s=SDIV
  *
  *  So FCLK=((2*(127+8)*Fin)) / ((2+2)*2^1)
  *         = (2*135*12MHz)/8
  *         = 405MHz
  *  For FCLK:HCLK:PCLK=1:4:8, so HCLK=100MHz, PCLK=50MHz
  ***************************************************************************************/
    mov r1, #ELFIN_CLOCK_POWER_BASE
    mov r2, #MDIV_405
    add r2, r2, #PSDIV_405
    str r2, [r1, #MPLLCON_OFFSET]
    /* Go to mem_init.S to Init memory controller register */
    bl    mem_init
    /* Set up the stack    */
stack_setup:
    ldr    r0, =STACK_BASE        /* upper 128 KiB: relocated uboot   */
    sub    r0, r0, #CONFIG_SYS_MALLOC_LEN    /* malloc area              */
    sub    r0, r0, #CONFIG_SYS_GBL_DATA_SIZE /* bdinfo                 */
    sub    sp, r0, #12        /* leave 3 words for abort-stack    */
    bic    sp, sp, #7        /* 8-byte alignment for ABI compliance */
clear_bss:
    ldr    r0, _bss_start        /* find start of bss segment        */
    ldr    r1, _bss_end        /* stop here                        */
    mov    r2, #0x00000000        /* clear                            */
clbss_l:str    r2, [r0]        /* clear loop...                    */
    add    r0, r0, #4
    cmp    r0, r1
    ble    clbss_l
#if 0  /*Don't wanna init BEEP & LED here*/
    bl  init_led_beep
    /*
     * R0,R1,R2 are the 1st,2nd, 3rd argument passed to C function
     * If need pass more than 3 arguments, then we need use stack.
     */
    mov r0,#LED1
    bl  turn_led_on
#endif
    bl  bootstrap_main
/*
 *************************************************************************
 *
 * Interrupt handling
 *
 *************************************************************************
 */
@
@ IRQ stack frame.
@
#define S_FRAME_SIZE    72
#define S_OLD_R0    68
#define S_PSR        64
#define S_PC        60
#define S_LR        56
#define S_SP        52
#define S_IP        48
#define S_FP        44
#define S_R10        40
#define S_R9        36
#define S_R8        32
#define S_R7        28
#define S_R6        24
#define S_R5        20
#define S_R4        16
#define S_R3        12
#define S_R2        8
#define S_R1        4
#define S_R0        0
#define MODE_SVC    0x13
#define I_BIT        0x80
/*
 * use bad_save_user_regs for abort/prefetch/undef/swi ...
 * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling
 */
    .macro    bad_save_user_regs
    sub    sp, sp, #S_FRAME_SIZE
    stmia    sp, {r0 - r12}            @ Calling r0-r12
    ldr    r2, _armboot_start
    sub    r2, r2, #(CONFIG_STACKSIZE)
    sub    r2, r2, #(CONFIG_SYS_MALLOC_LEN)
    /* set base 2 words into abort stack */
    sub    r2, r2, #(CONFIG_SYS_GBL_DATA_SIZE+8)
    ldmia    r2, {r2 - r3}            @ get pc, cpsr
    add    r0, sp, #S_FRAME_SIZE        @ restore sp_SVC
    add    r5, sp, #S_SP
    mov    r1, lr
    stmia    r5, {r0 - r3}            @ save sp_SVC, lr_SVC, pc, cpsr
    mov    r0, sp
    .endm
    .macro    irq_save_user_regs
    sub    sp, sp, #S_FRAME_SIZE
    stmia    sp, {r0 - r12}            @ Calling r0-r12
    add    r7, sp, #S_PC
    stmdb    r7, {sp, lr}^            @ Calling SP, LR
    str    lr, [r7, #0]            @ Save calling PC
    mrs    r6, spsr
    str    r6, [r7, #4]            @ Save CPSR
    str    r0, [r7, #8]            @ Save OLD_R0
    mov    r0, sp
    .endm
    .macro    irq_restore_user_regs
    ldmia    sp, {r0 - lr}^            @ Calling r0 - lr
    mov    r0, r0
    ldr    lr, [sp, #S_PC]            @ Get PC
    add    sp, sp, #S_FRAME_SIZE
    /* return & move spsr_svc into cpsr */
    subs    pc, lr, #4
    .endm
    .macro get_bad_stack
    ldr    r13, _armboot_start        @ setup our mode stack
    sub    r13, r13, #(CONFIG_STACKSIZE)
    sub    r13, r13, #(CONFIG_SYS_MALLOC_LEN)
    /* reserve a couple spots in abort stack */
    sub    r13, r13, #(CONFIG_SYS_GBL_DATA_SIZE+8)
    str    lr, [r13]            @ save caller lr / spsr
    mrs    lr, spsr
    str    lr, [r13, #4]
    mov    r13, #MODE_SVC            @ prepare SVC-Mode
    @ msr    spsr_c, r13
    msr    spsr, r13
    mov    lr, pc
    movs    pc, lr
    .endm
    .macro get_irq_stack            @ setup IRQ stack
    ldr    sp, IRQ_STACK_START
    .endm
    .macro get_fiq_stack            @ setup FIQ stack
    ldr    sp, FIQ_STACK_START
    .endm
/*
 * exception handlers
 */
    .align  5
undefined_instruction:
    get_bad_stack
    bad_save_user_regs
    bl    do_undefined_instruction
    .align    5
software_interrupt:
    get_bad_stack
    bad_save_user_regs
    bl    do_software_interrupt
    .align    5
prefetch_abort:
    get_bad_stack
    bad_save_user_regs
    bl    do_prefetch_abort
    .align    5
data_abort:
    get_bad_stack
    bad_save_user_regs
    bl    do_data_abort
    .align    5
not_used:
    get_bad_stack
    bad_save_user_regs
    bl    do_not_used
    .align    5
irq:
    get_bad_stack
    bad_save_user_regs
    bl    do_irq
    .align    5
fiq:
    get_bad_stack
    bad_save_user_regs
    bl    do_fiq
linux-bsp/asm-study/myboot/xmodem.c
New file
@@ -0,0 +1,121 @@
/********************************************************************************************
 *        File:  xmodem.c
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  Xmodem protocal used to download the second stage bootloader(launcher)
 *   ChangeLog:  1, Release initial version on "Tue Jul 12 16:43:18 CST 2011"
 *
 *******************************************************************************************/
#include <common.h>
#define XMODEM_SOH 0x01         /*Start Of Header, standard Xmodem */
#define XMODEM_STX 0x02         /*1K-Modem start Xmodem */
#define XMODEM_EOT 0x04         /*End Of Transmission */
#define XMODEM_ACK 0x06
#define XMODEM_NAK 0x15
#define XMODEM_CAN 0x18         /*Stop transmission */
#define XMODEM_EOF 0x1a         /*CTRL+Z EOF */
#define XMODEM_BLOCK_SIZE 128
static int xmodem_wait(void)
{
    long cnt = 0;
    while (!serial_is_recv_enable())
    {
        if (++cnt >= 2000000)
        {
            cnt = 0;
            serial_send_byte(XMODEM_NAK);
        }
    }
    return 0;
}
static int xmodem_read_block(unsigned char block_number, char *buf)
{
    unsigned char c, block_num, check_sum;
    int i;
    block_num = serial_recv_byte();
    if (block_num != block_number)
        return -1;
    block_num ^= serial_recv_byte();
    if (block_num != 0xff)
        return -1;
    check_sum = 0;
    for (i = 0; i < XMODEM_BLOCK_SIZE; i++)
    {
        c = serial_recv_byte();
        *(buf++) = c;
        check_sum += c;
    }
    check_sum ^= serial_recv_byte();
    if (check_sum)
        return -1;
    return i;
}
long xmodem_recv(char *buf)
{
    int r, receiving = 0;
    long size = 0;
    unsigned char c, block_number = 1;
    while (1)
    {
        if (!receiving)
            xmodem_wait();
        c = serial_recv_byte();
        switch (c)
        {
          case XMODEM_EOT:
              serial_send_byte(XMODEM_ACK);
              /*Remove the CMPEOF */
              long cnt = 0;
              if ((buf[-1] == XMODEM_EOF) && (buf[-2] == XMODEM_EOF) && (buf[-3] == XMODEM_EOF))
              {
                  while (size && buf[-cnt - 1] == XMODEM_EOF)
                      cnt++;
              }
              size -= cnt;
              goto RECV_OK;
          case XMODEM_CAN:
              return -1;
          case XMODEM_SOH:
              receiving++;
              r = xmodem_read_block(block_number, buf);
              if (r < 0)
              {
                  serial_send_byte(XMODEM_NAK);
              }
              else
              {
                  block_number++;
                  size += r;
                  buf += r;
                  serial_send_byte(XMODEM_ACK);
              }
              break;
          default:
              if (receiving)
                  return -1;
        }
    }
  RECV_OK:
    return size;
}
linux-bsp/asm-study/yaffs2/bootstrap.c
New file
@@ -0,0 +1,202 @@
/********************************************************************************************
 *        File:  bootstrap.c
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  This C code is the first stage bootloader(named bootstrap)
                 main code, test on FL2440 board.
 *   ChangeLog:  1, Release initial version on "Tue Jul 12 16:43:18 CST 2011"
 *
 *******************************************************************************************/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include "yaffsfs.h"
#include "s3c_board.h"
#define MALLOC_SIZE             20
int mkdir(const char *mp, const char *name)
{
    char full_name[100];
    sprintf(full_name, "%s/%s", mp, name);
    printf("Create directory [%s]\n", full_name);
    return yaffs_mkdir(full_name, S_IREAD| S_IWRITE);
}
int mkfile(const char *mp, const char *name)
{
    char full_name[100];
    char buf[100];
    int h;
    sprintf(full_name, "%s/%s", mp, name);
    h = yaffs_open(full_name, O_RDWR | O_CREAT | O_TRUNC, S_IREAD| S_IWRITE);
    yaffs_write(h, name, strlen(name));
    yaffs_lseek(h, 0, SEEK_SET);
    memset(buf, 0, sizeof(buf));
    yaffs_read(h, buf, sizeof(buf));
    printf("Create File [%s] content: [%s]\n", full_name, buf);
    yaffs_close(h);
    return 0;
}
int rm(const char *mp, const char *name)
{
    char full_name[100];
    if(name)
        sprintf(full_name, "%s/%s", mp, name);
    else
        strcpy(full_name, mp);
    printf("Remove %s\n", full_name);
    return yaffs_rm(full_name, 1);
}
int ls(const char *mp, const char *name)
{
    int recursive = 1;
    char full_name[100];
    if(name)
        sprintf(full_name, "%s/%s", mp, name);
    else
        strcpy(full_name, mp);
    printf("List folder '%s' %s recursive:\n", full_name, recursive?"with":"without");
    return yaffs_ls(full_name, recursive);
}
void dump_directory_tree_worker(const char *dname,int recursive)
{
    yaffs_DIR *d;
    struct yaffs_dirent *de;
    struct yaffs_stat s;
    char str[1000];
    d = yaffs_opendir(dname);
    if(!d)
    {
        printf("opendir failed\n");
    }
    else
    {
        while((de = yaffs_readdir(d)) != NULL)
        {
            sprintf(str,"%s/%s",dname,de->d_name);
            yaffs_lstat(str,&s);
            printf("%s inode %d obj %x length %lld mode %X ",
                str,s.st_ino,de->d_dont_use, s.st_size,s.st_mode);
            switch(s.st_mode & S_IFMT)
            {
                case S_IFREG: printf("data file"); break;
                case S_IFDIR: printf("directory"); break;
                case S_IFLNK: printf("symlink -->");
                              if(yaffs_readlink(str,str,100) < 0)
                                printf("no alias");
                              else
                                printf("\"%s\"",str);
                              break;
                default: printf("unknown"); break;
            }
            printf("\n");
            if((s.st_mode & S_IFMT) == S_IFDIR && recursive)
                dump_directory_tree_worker(str,1);
        }
        yaffs_closedir(d);
    }
}
static void dump_directory_tree(const char *dname)
{
    dump_directory_tree_worker(dname,1);
    printf("\n");
    printf("Free space in %s is %d\n\n",dname,(int)yaffs_freespace(dname));
}
void dumpDir(const char *dname)
{
    dump_directory_tree_worker(dname,0);
    printf("\n");
    printf("Free space in %s is %d\n\n",dname,(int)yaffs_freespace(dname));
}
void yaffs_test(const char *mountpt)
{
    yaffs_start_up();
#if 0
    yaffs_mount(mountpt);
    ls(mountpt, NULL);
    mkdir(mountpt, "foo");
    mkfile(mountpt, "foo/f1");
    return ;
#endif
    yaffs_format(mountpt,0,0,0);
    yaffs_mount(mountpt);
    printf("'%s' mounted\n", mountpt);
    mkdir(mountpt, "foo");
    mkfile(mountpt, "foo/f1");
    mkfile(mountpt, "foo/f2");
    mkfile(mountpt, "foo/f3");
    mkfile(mountpt, "foo/f4");
    mkdir(mountpt, "bar");
    mkfile(mountpt, "bar/f1");
    ls(mountpt, NULL);
    rm(mountpt, "foo/f4");
    rm(mountpt, "bar");
    ls(mountpt, NULL);
    printf("unmount and remount\n\n");
    /*  Unmount/remount yaffs_trace_mask */
    yaffs_unmount(mountpt);
    yaffs_mount(mountpt);
    ls(mountpt, NULL);
}
int bootstrap_main(void)
{
    char *ptr = NULL;
    int rv = -1;
    console_serial_init();
    printf("\b\n");
    printf("\bBootstrap nandflash yaffs2 test Version 0.0.1\n");
    /*  armboot_start is defined in the board-specific linker script */
    mem_malloc_init (TEXT_BASE - CONFIG_SYS_MALLOC_LEN, CONFIG_SYS_MALLOC_LEN);
    ptr = (char *)malloc(MALLOC_SIZE);
    strncpy(ptr, "Hello World!\n", MALLOC_SIZE);
    printf("Malloc address: %p, string: %s\n", ptr, ptr);
    free(ptr);
    yaffs_test(YAFFSFS_MNT_POINT);
hang:
    while(1)
        ;
    return 0;
}
linux-bsp/asm-study/yaffs2/bootstrap.lds
New file
@@ -0,0 +1,32 @@
/********************************************************************************************
 *        File:  bootstrap.lds
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  This is the LD linker configure script for bootstrap
 *   ChangeLog:  1, Release initial version on "Tue Jul 12 16:43:18 CST 2011"
 *
 *******************************************************************************************/
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS{
    . = ALIGN(4);
    .text   :
    {
      start.o   (.text)
      *(.text)
    }
    . = ALIGN(4);
    .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
    . = ALIGN(4);
    .rodata : { *(.rodata) }
    . = ALIGN(4);
    .data : { *(.data) }
    . = ALIGN(4);
    __bss_start = .;
    .bss : { *(.bss) }
    _end = .;
}
linux-bsp/asm-study/yaffs2/bsp/eabi_compat.c
New file
@@ -0,0 +1,29 @@
/*
 * Utility functions needed for (some) EABI conformant tool chains.
 *
 * (C) Copyright 2009 Wolfgang Denk <wd@denx.de>
 *
 * 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.
 */
#include <stdio.h>
#if 1
int raise (int signum)
{
//    printf("raise: Signal # %d caught\n", signum);
    return 0;
}
/* Dummy function to avoid linker complaints */
void __aeabi_unwind_cpp_pr0(void)
{
};
#else
void __aeabi_unwind_cpp_pr1(void)
{
};
#endif
linux-bsp/asm-study/yaffs2/bsp/k9f2g08_api.c
New file
@@ -0,0 +1,276 @@
/*
|  ECC MAIN  | BAD  | RES  |       YAFFS_TAG       |
|     4      |  4   |  8   |          48           |
*/
#include "k9f2g08_s3c.h"
/* From yaffs_guts.h */
#define YAFFS_OK    1
#define YAFFS_FAIL  0
int k9f2g08_init(void)
{
    return YAFFS_OK;
}
int k9f2g08_deinit(void)
{
    return YAFFS_OK;
}
static unsigned char wait_busy_status(void)
{
    unsigned char rc;
    for (rc=0; rc <40; rc++);
    bsp_nand_set_cs(0);
    bsp_nand_write_cmd(0x70);  // read status
    do {
        rc = bsp_nand_read_data8();
    } while ((rc & (1<<6)) == 0);
    bsp_nand_set_cs(1);
    return rc;
}
int k9f2g08_mark_block_bad(unsigned int blk_num)
{
    int row_addr = blk_num * 64;
    int col_addr = 2048;
    unsigned char status;
    bsp_nand_set_cs(0);
    bsp_nand_write_cmd(0x80);  // write command
    bsp_nand_write_addr((unsigned char)(col_addr >> 0));
    bsp_nand_write_addr((unsigned char)(col_addr >> 8));
    bsp_nand_write_addr((unsigned char)(row_addr >> 0));
    bsp_nand_write_addr((unsigned char)(row_addr >> 8));
    bsp_nand_write_addr((unsigned char)(row_addr >> 16));
    bsp_nand_write_data32(0xFFFFFFFF);
    bsp_nand_write_data32(0x00000000);
    bsp_nand_write_data32(0xFFFFFFFF);
    bsp_nand_write_data32(0xFFFFFFFF);
    bsp_nand_write_cmd(0x10);
    bsp_nand_set_cs(1);
    status = wait_busy_status();
    return (status & (1<<0)) ? YAFFS_FAIL : YAFFS_OK;
}
int k9f2g08_write(unsigned int chunk, const unsigned char *dat, const unsigned char *spare, unsigned int spare_size)
{
    int i;
    int col_addr;
    unsigned char status;
    if (dat) {
        col_addr = 0;
    } else {
        col_addr = 2048;
    }
    bsp_nand_set_cs(0);
    bsp_nand_write_cmd(0x80);  // write command
    bsp_nand_write_addr((unsigned char)(col_addr >> 0));
    bsp_nand_write_addr((unsigned char)(col_addr >> 8));
    bsp_nand_write_addr((unsigned char)(chunk >> 0));
    bsp_nand_write_addr((unsigned char)(chunk >> 8));
    bsp_nand_write_addr((unsigned char)(chunk >> 16));
    bsp_nand_start_main_ecc();
    if (dat) {
        for (i=0; i<2048; i++)
            bsp_nand_write_data8(*dat++);
    }
    bsp_nand_stop_main_ecc();
    bsp_nand_write_data32(bsp_nand_read_spare_ecc0());
    bsp_nand_write_data32(0xFFFFFFFF);
    bsp_nand_write_data32(0xFFFFFFFF);
    bsp_nand_write_data32(0xFFFFFFFF);
    if (spare) {
        for (i=0; i<spare_size; i++)
            bsp_nand_write_data8(*spare++);
    }
    bsp_nand_write_cmd(0x10);
    bsp_nand_set_cs(1);
    status = wait_busy_status();
    return (status & (1<<0)) ? YAFFS_FAIL : YAFFS_OK;
}
int k9f2g08_read(unsigned int chunk, unsigned char *dat, unsigned char *spare, unsigned int spare_size, int *eccStatus)
{
    int i;
    int col_addr;
    unsigned char *p = dat;
    unsigned int ecc = 0;
    int err_bit;
    int err_byte;
    if (dat) {
        col_addr = 0;
    } else {
        col_addr = 2048 + 16;
    }
    bsp_nand_set_cs(0);
    bsp_nand_write_cmd(0x00);  // read command
    bsp_nand_write_addr((unsigned char)(col_addr >> 0));
    bsp_nand_write_addr((unsigned char)(col_addr >> 8));
    bsp_nand_write_addr((unsigned char)(chunk >> 0));
    bsp_nand_write_addr((unsigned char)(chunk >> 8));
    bsp_nand_write_addr((unsigned char)(chunk >> 16));
    bsp_nand_write_cmd(0x30);  // read
    bsp_nand_wait_busy();
    if (dat) {
        bsp_nand_start_main_ecc();
        for (i=0; i<2048; i++)
            *p++ = bsp_nand_read_data8();
        bsp_nand_stop_main_ecc();
        ecc = bsp_nand_read_data32();
        bsp_nand_read_data32();
        bsp_nand_read_data32();
        bsp_nand_read_data32();
    }
    if (spare) {
        p = spare;
        for (i=0; i<spare_size; i++)
            *p++ = bsp_nand_read_data8();
    }
    bsp_nand_set_cs(1);
    if (dat) {
        i = bsp_nand_main_check_ecc(ecc, &err_byte, &err_bit);
        if (i == 0) {
            *eccStatus = 0;
            return 0;
        }
        if (i < 0) {
            *eccStatus = -1;
            return 0;
        }
        *eccStatus = 1;
        dat[err_byte] ^= (1<<err_bit);
    }
    return YAFFS_OK;
}
int k9f2g08_erase_block(unsigned int blk_num)
{
    unsigned char status;
    int chunk = blk_num * 64;
    bsp_nand_set_cs(0);
    bsp_nand_write_cmd(0x60);  // erase command
    bsp_nand_write_addr((unsigned char)(chunk >> 0));
    bsp_nand_write_addr((unsigned char)(chunk >> 8));
    bsp_nand_write_addr((unsigned char)(chunk >> 16));
    bsp_nand_write_cmd(0xD0);  // erase
    bsp_nand_set_cs(1);
    status = wait_busy_status();
    return (status & (1<<0)) ? YAFFS_FAIL : YAFFS_OK;
}
int k9f2g08_is_block_ok(unsigned int blk_num)
{
    int chunk = blk_num * 64;
    int col_addr = 2048 + 4;
    bsp_nand_set_cs(0);
    bsp_nand_write_cmd(0x00);  // read command
    bsp_nand_write_addr((unsigned char)(col_addr >> 0));
    bsp_nand_write_addr((unsigned char)(col_addr >> 8));
    bsp_nand_write_addr((unsigned char)(chunk >> 0));
    bsp_nand_write_addr((unsigned char)(chunk >> 8));
    bsp_nand_write_addr((unsigned char)(chunk >> 16));
    bsp_nand_write_cmd(0x30);  // read
    bsp_nand_wait_busy();
    int tmp = bsp_nand_read_data32();
    bsp_nand_set_cs(1);
    if (tmp == 0xFFFFFFFF) {
        return 1;
    }
    return 0;
}
int k9f2g08_read_id(unsigned int *id)
{
    int rc = -1;
    bsp_nand_set_cs(0);
    bsp_nand_write_cmd(0x90);  // read command
    bsp_nand_write_addr((unsigned char)0);
    do {
        if ((rc = bsp_nand_read_data8()) != 0xEC)
            break;
        *id = bsp_nand_read_data32();
        rc = 0;
    } while(0);
    bsp_nand_set_cs(1);
    return rc;
}
int k9f2g08_read_ll(unsigned int chunk, unsigned char *dat, unsigned char *spare)
{
    int i;
    int col_addr;
    unsigned char *p;
    if (dat) {
        col_addr = 0;
    } else {
        col_addr = 2048;
    }
    bsp_nand_set_cs(0);
    bsp_nand_write_cmd(0x00);  // read command
    bsp_nand_write_addr((unsigned char)(col_addr >> 0));
    bsp_nand_write_addr((unsigned char)(col_addr >> 8));
    bsp_nand_write_addr((unsigned char)(chunk >> 0));
    bsp_nand_write_addr((unsigned char)(chunk >> 8));
    bsp_nand_write_addr((unsigned char)(chunk >> 16));
    bsp_nand_write_cmd(0x30);  // read
    bsp_nand_wait_busy();
    if (dat) {
        p = dat;
        for (i=0; i<2048; i++)
            *p++ = bsp_nand_read_data8();
    }
    if (spare) {
        p = spare;
        for (i=0; i<64; i++)
            *p++ = bsp_nand_read_data8();
    }
    bsp_nand_set_cs(1);
    return 1;
}
linux-bsp/asm-study/yaffs2/bsp/k9f2g08_api.h
New file
@@ -0,0 +1,14 @@
#ifndef __K9F2G08_API_H__
#define __K9F2G08_API_H__
int k9f2g08_init(void);
int k9f2g08_deinit(void);
int k9f2g08_mark_block_bad(unsigned int blk_num);
int k9f2g08_write(unsigned int chunk, const unsigned char *dat, const unsigned char *spare, unsigned int spare_size);
int k9f2g08_read(unsigned int chunk, unsigned char *dat, unsigned char *spare, unsigned int spare_size, int *eccStatus);
int k9f2g08_read_ll(unsigned int chunk, unsigned char *dat, unsigned char *spare);
int k9f2g08_erase_block(unsigned int blk_num);
int k9f2g08_is_block_ok(unsigned int blk_num);
int k9f2g08_read_id(unsigned int *id);
#endif  // __K9F2G08_API_H__
linux-bsp/asm-study/yaffs2/bsp/k9f2g08_s3c.h
New file
@@ -0,0 +1,177 @@
#ifndef __K9F2G08_S3C_H__
#define __K9F2G08_S3C_H__
#include "s3c2440.h"
static inline void bsp_init_nand(void)
{
    unsigned int  reg;
    struct s3c2440_clock_power *clkpwr = s3c2440_get_base_clock_power();
     clkpwr->CLKCON |= (1<<4);
    struct s3c2440_gpio *gpio = s3c2440_get_base_gpio();
    struct s3c2440_nand *nand = s3c2440_get_base_nand();
    reg = gpio->GPACON;
    reg |= (1<<22) | (1<<20) | (1<<19) | (1<<18) | (1<<17);
    gpio->GPACON = reg;
    nand->NFCONF = (1<<12) | (1<<8) | (1<<4) | (1<<3) |(1<<2) | (1<<5) | (0<<0);
    nand->NFCONT = 3;
}
static inline void bsp_nand_set_cs(int level)
{
    struct s3c2440_nand *nand = s3c2440_get_base_nand();
    if (level == 0) {
        nand->NFCONT &= ~(1<<1);
//        while (nand->NFSTAT & (1<<1));
    } else {
        nand->NFCONT |= 1<<1;
//        while ((nand->NFSTAT & (1<<1)) == 0);
    }
}
static inline void bsp_nand_start_main_ecc(void)
{
    struct s3c2440_nand *nand = s3c2440_get_base_nand();
    nand->NFCONT |= (1<<6) | (1<<5);  // unlock all
    nand->NFCONT |= (1<<4);  // init ecc
    nand->NFCONT &= ~(1<<6);  // lock spare
}
static inline void bsp_nand_stop_main_ecc(void)
{
    struct s3c2440_nand *nand = s3c2440_get_base_nand();
    nand->NFCONT |= (1<<5);  // lock main
}
static inline void bsp_nand_start_spare_ecc(void)
{
    struct s3c2440_nand *nand = s3c2440_get_base_nand();
    nand->NFCONT &= ~(1<<6); // unlock spare
}
static inline void bsp_nand_stop_spare_ecc(void)
{
    struct s3c2440_nand *nand = s3c2440_get_base_nand();
    nand->NFCONT |= (1<<6); // lock spare
}
static inline int bsp_nand_spare_check_ecc(unsigned short ecc, int *err_byte, int *err_bit)
{
    struct s3c2440_nand *nand = s3c2440_get_base_nand();
    unsigned int ecc_wr = ((ecc & 0xFF00) << 8) | (ecc & 0x00FF);
    nand->NFSECCD = ecc_wr;
    int err = nand->NFESTAT0;
    if ((err & (3<<2)) == (0<<2))  // no err
        return 0;
    if ((err & (3<<2)) == (1<<2)) {  // 1 bit err
        *err_byte = (err >> 21) & 0x0F;
        *err_bit = (err >> 18) & 0x07;
        return 1;
    }
    return -1;
}
static inline int bsp_nand_main_check_ecc(unsigned int ecc, int *err_byte, int *err_bit)
{
    struct s3c2440_nand *nand = s3c2440_get_base_nand();
    unsigned int ecc_wr = ((ecc & 0xFF00) << 8) | (ecc & 0x00FF);
    nand->NFMECCD0 = ecc_wr;
    ecc_wr = ((ecc & 0xFF000000) >> 8) | ((ecc & 0x00FF0000) >> 16);
    nand->NFMECCD1 = ecc_wr;
    int err = nand->NFESTAT0;
    if ((err & (3<<0)) == (0<<0))  // no err
        return 0;
    if ((err & (3<<0)) == (1<<0)) {  // no err
        *err_byte = (err >> 7) & 0x7FF;
        *err_bit = (err >> 4) & 0x07;
        return 1;
    }
    return -1;
}
static inline void bsp_nand_write_cmd(unsigned char cmd)
{
    struct s3c2440_nand *nand = s3c2440_get_base_nand();
    nand->NFCMD = cmd;
}
static inline void bsp_nand_write_addr(unsigned char addr)
{
    struct s3c2440_nand *nand = s3c2440_get_base_nand();
    nand->NFADDR = addr;
}
static inline void bsp_nand_write_data32(unsigned int dat)
{
    *(volatile unsigned int *)(&(s3c2440_get_base_nand()->NFDATA)) = dat;
}
static inline void bsp_nand_write_data16(unsigned short dat)
{
    *(volatile unsigned short *)(&(s3c2440_get_base_nand()->NFDATA)) = dat;
}
static inline void bsp_nand_write_data8(unsigned char dat)
{
    *(volatile unsigned char *)(&(s3c2440_get_base_nand()->NFDATA)) = dat;
}
static inline unsigned int bsp_nand_read_data32(void)
{
    return *(volatile unsigned int *)(&(s3c2440_get_base_nand()->NFDATA));
}
static inline unsigned short bsp_nand_read_data16(void)
{
    return *(volatile unsigned short *)(&(s3c2440_get_base_nand()->NFDATA));
}
static inline unsigned char bsp_nand_read_data8(void)
{
    return *(volatile unsigned char *)(&(s3c2440_get_base_nand()->NFDATA));
}
static inline unsigned short bsp_nand_read_spare_ecc0(void)
{
    struct s3c2440_nand *nand = s3c2440_get_base_nand();
    return nand->NFSECC & 0xFFFF;
}
static inline unsigned int bsp_nand_read_main_ecc0(void)
{
    struct s3c2440_nand *nand = s3c2440_get_base_nand();
    return nand->NFMECC0;
}
static inline void bsp_nand_wait_busy(void)
{
    int i;
    for (i=10; i>0; i--);
    struct s3c2440_nand *nand = s3c2440_get_base_nand();
    while ((nand->NFSTAT & (1<<0)) == 0);
}
#endif //__K9F2G08_S3C_H__
linux-bsp/asm-study/yaffs2/bsp/makefile
New file
@@ -0,0 +1,102 @@
#*********************************************************************************
#      Copyright:  (C) 2012 CoherentPlus Sdn. Bhd.
#                  All rights reserved.
#
#       Filename:  Makefile
#    Description:  This is the common subdir Makefile which to compile all the C
#                  source code to object files and then generate the shared or
#                  static library named lib$(FOLDER_NAME).a orlib $(FOLDER_NAME).so,
#                  which depends on the variable $LINK_MODE.
#
#        Version:  1.0.0(10/08/2011~)
#                  Author:  Guo Wenxue <guowenxue@gmail.com>
#      ChangeLog:  1, Release initial version on "10/08/2011 01:29:33 AM"
#
#********************************************************************************/
PWD=$(shell pwd)
LOCAL_COMPILE=YES
LINK_MODE=STATIC
#If wanna compile in the subdir, not called by top makefile, uncomment it
ifneq (${TOP_COMPILE}, YES)
LOCAL_COMPILE=YES
endif
LIBNAME=$(shell basename ${PWD})
STALIB=lib${LIBNAME}.a
DYNLIB=lib${LIBNAME}.so
VPATH= .
C_SRCS = $(wildcard ${VPATH}/*.c)
AS_SRCS = $(wildcard ${VPATH}/*.S)
OBJS = $(patsubst %.c,%.o,$(C_SRCS))
OBJS += $(patsubst %.S,%.o,$(AS_SRCS))
#======================================================
#  ---> Doesn't call by top makefile, compile by local
#======================================================
ifeq (${LOCAL_COMPILE}, YES)
ARCH?=arm920t
#ARCH?=i386
CFLAGS+=-fPIC
TMP=$(shell echo $(ARCH) | tr "[A-Z]" "[a-z]")
ifneq (,$(filter i386,$(TMP)))
    CROSS_COMPILE=
else
    CROSS_COMPILE=/opt/xtools/arm920t/bin/arm-linux-
endif
PRJDIR?=$(shell pwd)
CFLAGS+=-I${PRJDIR}
CC = ${CROSS_COMPILE}gcc
AR = ${CROSS_COMPILE}ar
endif #End local compile
ifeq ("${LINK_MODE}", "STATIC")
    LIBS = ${STALIB}
else
    LIBS=${DYNLIB}
endif
all: entry ${LIBS} install
entry:
    @echo " ";
    @echo " =========================================================";
    @echo " **     Compile subdir ${LIBNAME} for ${ARCH}             ";
    @echo " =========================================================";
#$(LD) -g --relocatable $(OBJS) -o lib${LIBNAME}.o
${STALIB}:    $(OBJS)
    $(AR) -rcu $@ $(OBJS)
${DYNLIB}:   $(OBJS)
    $(CC) -fPIC -shared -o $@ $(OBJS)
%.o: %.S
    $(CC) $(AFLAGS) -c -o $@ $<
%.o : %.c
    $(CC) -c $< $(CFLAGS)
tag:
    @ctags --c-kinds=+defglmnstuvx --langmap=c:.c.h.ho.hem.het.hec.hev.him.hit.hic.hiv -R .
    @cscope -Rbq
install:
    @if [ ! -z "${LIBS_PATH}" ] ; then \
        mkdir -p ${LIBS_PATH} ; \
        cp ${LIBS} ${LIBS_PATH}; \
    fi;
clean:
    @rm -f *.o
    @rm -rf *.gdb *.a *.so
distclean: clean
    @rm -f  tags cscope*
.PHONY: clean entry
linux-bsp/asm-study/yaffs2/bsp/s3c2440.h
New file
@@ -0,0 +1,646 @@
#ifndef __S3C2440_H__
#define __S3C2440_H__
#define S3C2440_UART_CHANNELS    3
#define S3C2440_SPI_CHANNELS    2
/* Memory controller (see manual chapter 5) */
struct s3c2440_memctl {
    volatile unsigned int    BWSCON;
    volatile unsigned int    BANKCON[8];
    volatile unsigned int    REFRESH;
    volatile unsigned int    BANKSIZE;
    volatile unsigned int    MRSRB6;
    volatile unsigned int    MRSRB7;
};
/* USB HOST (see manual chapter 12) */
struct s3c2440_usb_host {
    volatile unsigned int    HcRevision;
    volatile unsigned int    HcControl;
    volatile unsigned int    HcCommonStatus;
    volatile unsigned int    HcInterruptStatus;
    volatile unsigned int    HcInterruptEnable;
    volatile unsigned int    HcInterruptDisable;
    volatile unsigned int    HcHCCA;
    volatile unsigned int    HcPeriodCuttendED;
    volatile unsigned int    HcControlHeadED;
    volatile unsigned int    HcControlCurrentED;
    volatile unsigned int    HcBulkHeadED;
    volatile unsigned int    HcBuldCurrentED;
    volatile unsigned int    HcDoneHead;
    volatile unsigned int    HcRmInterval;
    volatile unsigned int    HcFmRemaining;
    volatile unsigned int    HcFmNumber;
    volatile unsigned int    HcPeriodicStart;
    volatile unsigned int    HcLSThreshold;
    volatile unsigned int    HcRhDescriptorA;
    volatile unsigned int    HcRhDescriptorB;
    volatile unsigned int    HcRhStatus;
    volatile unsigned int    HcRhPortStatus1;
    volatile unsigned int    HcRhPortStatus2;
};
/* INTERRUPT (see manual chapter 14) */
struct s3c2440_interrupt {
    volatile unsigned int    SRCPND;
    volatile unsigned int    INTMOD;
    volatile unsigned int    INTMSK;
    volatile unsigned int    PRIORITY;
    volatile unsigned int    INTPND;
    volatile unsigned int    INTOFFSET;
    volatile unsigned int    SUBSRCPND;
    volatile unsigned int    INTSUBMSK;
};
/* DMAS (see manual chapter 8) */
struct s3c2440_dma {
    volatile unsigned int    DISRC;
    volatile unsigned int    DISRCC;
    volatile unsigned int    DIDST;
    volatile unsigned int    DIDSTC;
    volatile unsigned int    DCON;
    volatile unsigned int    DSTAT;
    volatile unsigned int    DCSRC;
    volatile unsigned int    DCDST;
    volatile unsigned int    DMASKTRIG;
    volatile unsigned int    res[7];
};
struct s3c2440_dmas {
    struct s3c2440_dma    dma[4];
};
struct s3c2440_clock_power {
    volatile unsigned int    LOCKTIME;
    volatile unsigned int    MPLLCON;
    volatile unsigned int    UPLLCON;
    volatile unsigned int    CLKCON;
    volatile unsigned int    CLKSLOW;
    volatile unsigned int    CLKDIVN;
    volatile unsigned int CAMDIVN;
};
/* LCD CONTROLLER (see manual chapter 15) */
struct s3c2440_lcd {
    volatile unsigned int    LCDCON1;
    volatile unsigned int    LCDCON2;
    volatile unsigned int    LCDCON3;
    volatile unsigned int    LCDCON4;
    volatile unsigned int    LCDCON5;
    volatile unsigned int    LCDSADDR1;
    volatile unsigned int    LCDSADDR2;
    volatile unsigned int    LCDSADDR3;
    volatile unsigned int    REDLUT;
    volatile unsigned int    GREENLUT;
    volatile unsigned int    BLUELUT;
    volatile unsigned int    res[8];
    volatile unsigned int    DITHMODE;
    volatile unsigned int    TPAL;
    volatile unsigned int    LCDINTPND;
    volatile unsigned int    LCDSRCPND;
    volatile unsigned int    LCDINTMSK;
    volatile unsigned int    TCONSEL;
};
/* NAND FLASH (see S3C2440 manual chapter 6) */
struct s3c2440_nand {
    volatile unsigned int    NFCONF;
    volatile unsigned int    NFCONT;
    volatile unsigned int    NFCMD;
    volatile unsigned int    NFADDR;
    volatile unsigned int    NFDATA;
    volatile unsigned int    NFMECCD0;
    volatile unsigned int    NFMECCD1;
    volatile unsigned int    NFSECCD;
    volatile unsigned int    NFSTAT;
    volatile unsigned int    NFESTAT0;
    volatile unsigned int    NFESTAT1;
    volatile unsigned int    NFMECC0;
    volatile unsigned int    NFMECC1;
    volatile unsigned int    NFSECC;
    volatile unsigned int    NFSBLK;
    volatile unsigned int    NFEBLK;
};
/* UART (see manual chapter 11) */
struct s3c2440_uart {
    volatile unsigned int    ULCON;
    volatile unsigned int    UCON;
    volatile unsigned int    UFCON;
    volatile unsigned int    UMCON;
    volatile unsigned int    UTRSTAT;
    volatile unsigned int    UERSTAT;
    volatile unsigned int    UFSTAT;
    volatile unsigned int    UMSTAT;
#ifdef __BIG_ENDIAN
    volatile unsigned char    res1[3];
    volatile unsigned char    UTXH;
    volatile unsigned char    res2[3];
    volatile unsigned char    URXH;
#else /* Little Endian */
    volatile unsigned char    UTXH;
    volatile unsigned char    res1[3];
    volatile unsigned char    URXH;
    volatile unsigned char    res2[3];
#endif
    volatile unsigned int    UBRDIV;
};
/* PWM TIMER (see manual chapter 10) */
struct s3c2440_timer {
    volatile unsigned int    TCNTB;
    volatile unsigned int    TCMPB;
    volatile unsigned int    TCNTO;
};
struct s3c2440_timers {
    volatile unsigned int    TCFG0;
    volatile unsigned int    TCFG1;
    volatile unsigned int    TCON;
    struct s3c2440_timer    ch[4];
    volatile unsigned int    TCNTB4;
    volatile unsigned int    TCNTO4;
};
/* USB DEVICE (see manual chapter 13) */
struct s3c2440_usb_dev_fifos {
#ifdef __BIG_ENDIAN
    volatile unsigned char    res[3];
    volatile unsigned char    EP_FIFO_REG;
#else /*  little endian */
    volatile unsigned char    EP_FIFO_REG;
    volatile unsigned char    res[3];
#endif
};
struct s3c2440_usb_dev_dmas {
#ifdef __BIG_ENDIAN
    volatile unsigned char    res1[3];
    volatile unsigned char    EP_DMA_CON;
    volatile unsigned char    res2[3];
    volatile unsigned char    EP_DMA_UNIT;
    volatile unsigned char    res3[3];
    volatile unsigned char    EP_DMA_FIFO;
    volatile unsigned char    res4[3];
    volatile unsigned char    EP_DMA_TTC_L;
    volatile unsigned char    res5[3];
    volatile unsigned char    EP_DMA_TTC_M;
    volatile unsigned char    res6[3];
    volatile unsigned char    EP_DMA_TTC_H;
#else /*  little endian */
    volatile unsigned char    EP_DMA_CON;
    volatile unsigned char    res1[3];
    volatile unsigned char    EP_DMA_UNIT;
    volatile unsigned char    res2[3];
    volatile unsigned char    EP_DMA_FIFO;
    volatile unsigned char    res3[3];
    volatile unsigned char    EP_DMA_TTC_L;
    volatile unsigned char    res4[3];
    volatile unsigned char    EP_DMA_TTC_M;
    volatile unsigned char    res5[3];
    volatile unsigned char    EP_DMA_TTC_H;
    volatile unsigned char    res6[3];
#endif
};
struct s3c2440_usb_device {
#ifdef __BIG_ENDIAN
    volatile unsigned char    res1[3];
    volatile unsigned char    FUNC_ADDR_REG;
    volatile unsigned char    res2[3];
    volatile unsigned char    PWR_REG;
    volatile unsigned char    res3[3];
    volatile unsigned char    EP_INT_REG;
    volatile unsigned char    res4[15];
    volatile unsigned char    USB_INT_REG;
    volatile unsigned char    res5[3];
    volatile unsigned char    EP_INT_EN_REG;
    volatile unsigned char    res6[15];
    volatile unsigned char    USB_INT_EN_REG;
    volatile unsigned char    res7[3];
    volatile unsigned char    FRAME_NUM1_REG;
    volatile unsigned char    res8[3];
    volatile unsigned char    FRAME_NUM2_REG;
    volatile unsigned char    res9[3];
    volatile unsigned char    INDEX_REG;
    volatile unsigned char    res10[7];
    volatile unsigned char    MAXP_REG;
    volatile unsigned char    res11[3];
    volatile unsigned char    EP0_CSR_IN_CSR1_REG;
    volatile unsigned char    res12[3];
    volatile unsigned char    IN_CSR2_REG;
    volatile unsigned char    res13[7];
    volatile unsigned char    OUT_CSR1_REG;
    volatile unsigned char    res14[3];
    volatile unsigned char    OUT_CSR2_REG;
    volatile unsigned char    res15[3];
    volatile unsigned char    OUT_FIFO_CNT1_REG;
    volatile unsigned char    res16[3];
    volatile unsigned char    OUT_FIFO_CNT2_REG;
#else /*  little endian */
    volatile unsigned char    FUNC_ADDR_REG;
    volatile unsigned char    res1[3];
    volatile unsigned char    PWR_REG;
    volatile unsigned char    res2[3];
    volatile unsigned char    EP_INT_REG;
    volatile unsigned char    res3[15];
    volatile unsigned char    USB_INT_REG;
    volatile unsigned char    res4[3];
    volatile unsigned char    EP_INT_EN_REG;
    volatile unsigned char    res5[15];
    volatile unsigned char    USB_INT_EN_REG;
    volatile unsigned char    res6[3];
    volatile unsigned char    FRAME_NUM1_REG;
    volatile unsigned char    res7[3];
    volatile unsigned char    FRAME_NUM2_REG;
    volatile unsigned char    res8[3];
    volatile unsigned char    INDEX_REG;
    volatile unsigned char    res9[7];
    volatile unsigned char    MAXP_REG;
    volatile unsigned char    res10[7];
    volatile unsigned char    EP0_CSR_IN_CSR1_REG;
    volatile unsigned char    res11[3];
    volatile unsigned char    IN_CSR2_REG;
    volatile unsigned char    res12[3];
    volatile unsigned char    OUT_CSR1_REG;
    volatile unsigned char    res13[7];
    volatile unsigned char    OUT_CSR2_REG;
    volatile unsigned char    res14[3];
    volatile unsigned char    OUT_FIFO_CNT1_REG;
    volatile unsigned char    res15[3];
    volatile unsigned char    OUT_FIFO_CNT2_REG;
    volatile unsigned char    res16[3];
#endif /*  __BIG_ENDIAN */
    struct s3c2440_usb_dev_fifos    fifo[5];
    struct s3c2440_usb_dev_dmas    dma[5];
};
/* WATCH DOG TIMER (see manual chapter 18) */
struct s3c2440_watchdog {
    volatile unsigned int    WTCON;
    volatile unsigned int    WTDAT;
    volatile unsigned int    WTCNT;
};
/* IIC (see manual chapter 20) */
struct s3c2440_i2c {
    volatile unsigned int    IICCON;
    volatile unsigned int    IICSTAT;
    volatile unsigned int    IICADD;
    volatile unsigned int    IICDS;
};
/* IIS (see manual chapter 21) */
struct s3c2440_i2s {
#ifdef __BIG_ENDIAN
    volatile unsigned short    res1;
    volatile unsigned short    IISCON;
    volatile unsigned short    res2;
    volatile unsigned short    IISMOD;
    volatile unsigned short    res3;
    volatile unsigned short    IISPSR;
    volatile unsigned short    res4;
    volatile unsigned short    IISFCON;
    volatile unsigned short    res5;
    volatile unsigned short    IISFIFO;
#else /*  little endian */
    volatile unsigned short    IISCON;
    volatile unsigned short    res1;
    volatile unsigned short    IISMOD;
    volatile unsigned short    res2;
    volatile unsigned short    IISPSR;
    volatile unsigned short    res3;
    volatile unsigned short    IISFCON;
    volatile unsigned short    res4;
    volatile unsigned short    IISFIFO;
    volatile unsigned short    res5;
#endif
};
/* I/O PORT (see manual chapter 9) */
struct s3c2440_gpio {
    volatile unsigned int    GPACON;
    volatile unsigned int    GPADAT;
    volatile unsigned int    res1[2];
    volatile unsigned int    GPBCON;
    volatile unsigned int    GPBDAT;
    volatile unsigned int    GPBUP;
    volatile unsigned int    res2;
    volatile unsigned int    GPCCON;
    volatile unsigned int    GPCDAT;
    volatile unsigned int    GPCUP;
    volatile unsigned int    res3;
    volatile unsigned int    GPDCON;
    volatile unsigned int    GPDDAT;
    volatile unsigned int    GPDUP;
    volatile unsigned int    res4;
    volatile unsigned int    GPECON;
    volatile unsigned int    GPEDAT;
    volatile unsigned int    GPEUP;
    volatile unsigned int    res5;
    volatile unsigned int    GPFCON;
    volatile unsigned int    GPFDAT;
    volatile unsigned int    GPFUP;
    volatile unsigned int    res6;
    volatile unsigned int    GPGCON;
    volatile unsigned int    GPGDAT;
    volatile unsigned int    GPGUP;
    volatile unsigned int    res7;
    volatile unsigned int    GPHCON;
    volatile unsigned int    GPHDAT;
    volatile unsigned int    GPHUP;
    volatile unsigned int    res8;
    volatile unsigned int    MISCCR;
    volatile unsigned int    DCLKCON;
    volatile unsigned int    EXTINT0;
    volatile unsigned int    EXTINT1;
    volatile unsigned int    EXTINT2;
    volatile unsigned int    EINTFLT0;
    volatile unsigned int    EINTFLT1;
    volatile unsigned int    EINTFLT2;
    volatile unsigned int    EINTFLT3;
    volatile unsigned int    EINTMASK;
    volatile unsigned int    EINTPEND;
    volatile unsigned int    GSTATUS0;
    volatile unsigned int    GSTATUS1;
    volatile unsigned int    GSTATUS2;
    volatile unsigned int    GSTATUS3;
    volatile unsigned int    GSTATUS4;
};
/* RTC (see manual chapter 17) */
struct s3c2440_rtc {
#ifdef __BIG_ENDIAN
    volatile unsigned char    res1[67];
    volatile unsigned char    RTCCON;
    volatile unsigned char    res2[3];
    volatile unsigned char    TICNT;
    volatile unsigned char    res3[11];
    volatile unsigned char    RTCALM;
    volatile unsigned char    res4[3];
    volatile unsigned char    ALMSEC;
    volatile unsigned char    res5[3];
    volatile unsigned char    ALMMIN;
    volatile unsigned char    res6[3];
    volatile unsigned char    ALMHOUR;
    volatile unsigned char    res7[3];
    volatile unsigned char    ALMDATE;
    volatile unsigned char    res8[3];
    volatile unsigned char    ALMMON;
    volatile unsigned char    res9[3];
    volatile unsigned char    ALMYEAR;
    volatile unsigned char    res10[3];
    volatile unsigned char    RTCRST;
    volatile unsigned char    res11[3];
    volatile unsigned char    BCDSEC;
    volatile unsigned char    res12[3];
    volatile unsigned char    BCDMIN;
    volatile unsigned char    res13[3];
    volatile unsigned char    BCDHOUR;
    volatile unsigned char    res14[3];
    volatile unsigned char    BCDDATE;
    volatile unsigned char    res15[3];
    volatile unsigned char    BCDDAY;
    volatile unsigned char    res16[3];
    volatile unsigned char    BCDMON;
    volatile unsigned char    res17[3];
    volatile unsigned char    BCDYEAR;
#else /*  little endian */
    volatile unsigned char    res0[64];
    volatile unsigned char    RTCCON;
    volatile unsigned char    res1[3];
    volatile unsigned char    TICNT;
    volatile unsigned char    res2[11];
    volatile unsigned char    RTCALM;
    volatile unsigned char    res3[3];
    volatile unsigned char    ALMSEC;
    volatile unsigned char    res4[3];
    volatile unsigned char    ALMMIN;
    volatile unsigned char    res5[3];
    volatile unsigned char    ALMHOUR;
    volatile unsigned char    res6[3];
    volatile unsigned char    ALMDATE;
    volatile unsigned char    res7[3];
    volatile unsigned char    ALMMON;
    volatile unsigned char    res8[3];
    volatile unsigned char    ALMYEAR;
    volatile unsigned char    res9[3];
    volatile unsigned char    RTCRST;
    volatile unsigned char    res10[3];
    volatile unsigned char    BCDSEC;
    volatile unsigned char    res11[3];
    volatile unsigned char    BCDMIN;
    volatile unsigned char    res12[3];
    volatile unsigned char    BCDHOUR;
    volatile unsigned char    res13[3];
    volatile unsigned char    BCDDATE;
    volatile unsigned char    res14[3];
    volatile unsigned char    BCDDAY;
    volatile unsigned char    res15[3];
    volatile unsigned char    BCDMON;
    volatile unsigned char    res16[3];
    volatile unsigned char    BCDYEAR;
    volatile unsigned char    res17[3];
#endif
};
/* ADC (see manual chapter 16) */
struct s3c2440_adc {
    volatile unsigned int    ADCCON;
    volatile unsigned int    ADCTSC;
    volatile unsigned int    ADCDLY;
    volatile unsigned int    ADCDAT0;
    volatile unsigned int    ADCDAT1;
    volatile unsigned int ADCUPDN;
};
/* SPI (see manual chapter 22) */
struct s3c2440_spi_channel {
    volatile unsigned char    SPCON;
    volatile unsigned char    res1[3];
    volatile unsigned char    SPSTA;
    volatile unsigned char    res2[3];
    volatile unsigned char    SPPIN;
    volatile unsigned char    res3[3];
    volatile unsigned char    SPPRE;
    volatile unsigned char    res4[3];
    volatile unsigned char    SPTDAT;
    volatile unsigned char    res5[3];
    volatile unsigned char    SPRDAT;
    volatile unsigned char    res6[3];
    volatile unsigned char    res7[16];
};
struct s3c2440_spi {
    struct s3c2440_spi_channel    ch[S3C2440_SPI_CHANNELS];
};
struct s3c2440_sdi {
    volatile unsigned int    SDICON;
    volatile unsigned int    SDIPRE;
    volatile unsigned int    SDICARG;
    volatile unsigned int    SDICCON;
    volatile unsigned int    SDICSTA;
    volatile unsigned int    SDIRSP0;
    volatile unsigned int    SDIRSP1;
    volatile unsigned int    SDIRSP2;
    volatile unsigned int    SDIRSP3;
    volatile unsigned int    SDIDTIMER;
    volatile unsigned int    SDIBSIZE;
    volatile unsigned int    SDIDCON;
    volatile unsigned int    SDIDCNT;
    volatile unsigned int    SDIDSTA;
    volatile unsigned int    SDIFSTA;
#ifdef __BIG_ENDIAN
    volatile unsigned char    res[3];
    volatile unsigned char    SDIDAT;
#else
    volatile unsigned char    SDIDAT;
    volatile unsigned char    res[3];
#endif
    volatile unsigned int    SDIIMSK;
};
/* S3C2440 only supports 512 Byte HW ECC */
#define S3C2440_ECCSIZE        512
#define S3C2440_ECCBYTES    3
enum s3c2440_uarts_nr {
    S3C2440_UART0 = 0,
    S3C2440_UART1 = 1,
    S3C2440_UART2 = 2
};
/* S3C2440 device base addresses */
#define S3C2440_MEMCTL_BASE            0x48000000
#define S3C2440_USB_HOST_BASE        0x49000000
#define S3C2440_INTERRUPT_BASE        0x4A000000
#define S3C2440_DMA_BASE            0x4B000000
#define S3C2440_CLOCK_POWER_BASE    0x4C000000
#define S3C2440_LCD_BASE            0x4D000000
#define S3C2440_NAND_BASE            0x4E000000
#define S3C2440_UART_BASE            0x50000000
#define S3C2440_TIMER_BASE            0x51000000
#define S3C2440_USB_DEVICE_BASE        0x52000140
#define S3C2440_WATCHDOG_BASE        0x53000000
#define S3C2440_I2C_BASE            0x54000000
#define S3C2440_I2S_BASE            0x55000000
#define S3C2440_GPIO_BASE            0x56000000
#define S3C2440_RTC_BASE            0x57000000
#define S3C2440_ADC_BASE            0x58000000
#define S3C2440_SPI_BASE            0x59000000
#define S3C2440_SDI_BASE            0x5A000000
static inline struct s3c2440_memctl *s3c2440_get_base_memctl(void)
{
    return (struct s3c2440_memctl *)S3C2440_MEMCTL_BASE;
}
static inline struct s3c2440_usb_host *s3c2440_get_base_usb_host(void)
{
    return (struct s3c2440_usb_host *)S3C2440_USB_HOST_BASE;
}
static inline struct s3c2440_interrupt *s3c2440_get_base_interrupt(void)
{
    return (struct s3c2440_interrupt *)S3C2440_INTERRUPT_BASE;
}
static inline struct s3c2440_dmas *s3c2440_get_base_dmas(void)
{
    return (struct s3c2440_dmas *)S3C2440_DMA_BASE;
}
static inline struct s3c2440_clock_power *s3c2440_get_base_clock_power(void)
{
    return (struct s3c2440_clock_power *)S3C2440_CLOCK_POWER_BASE;
}
static inline struct s3c2440_lcd *s3c2440_get_base_lcd(void)
{
    return (struct s3c2440_lcd *)S3C2440_LCD_BASE;
}
static inline struct s3c2440_nand *s3c2440_get_base_nand(void)
{
    return (struct s3c2440_nand *)S3C2440_NAND_BASE;
}
static inline struct s3c2440_uart *s3c2440_get_base_uart(enum s3c2440_uarts_nr n)
{
    return (struct s3c2440_uart *)(S3C2440_UART_BASE + (n * 0x4000));
}
static inline struct s3c2440_timers *s3c2440_get_base_timers(void)
{
    return (struct s3c2440_timers *)S3C2440_TIMER_BASE;
}
static inline struct s3c2440_usb_device *s3c2440_get_base_usb_device(void)
{
    return (struct s3c2440_usb_device *)S3C2440_USB_DEVICE_BASE;
}
static inline struct s3c2440_watchdog *s3c2440_get_base_watchdog(void)
{
    return (struct s3c2440_watchdog *)S3C2440_WATCHDOG_BASE;
}
static inline struct s3c2440_i2c *s3c2440_get_base_i2c(void)
{
    return (struct s3c2440_i2c *)S3C2440_I2C_BASE;
}
static inline struct s3c2440_i2s *s3c2440_get_base_i2s(void)
{
    return (struct s3c2440_i2s *)S3C2440_I2S_BASE;
}
static inline struct s3c2440_gpio *s3c2440_get_base_gpio(void)
{
    return (struct s3c2440_gpio *)S3C2440_GPIO_BASE;
}
static inline struct s3c2440_rtc *s3c2440_get_base_rtc(void)
{
    return (struct s3c2440_rtc *)S3C2440_RTC_BASE;
}
static inline struct s3c2440_adc *s3c2440_get_base_adc(void)
{
    return (struct s3c2440_adc *)S3C2440_ADC_BASE;
}
static inline struct s3c2440_spi *s3c2440_get_base_spi(void)
{
    return (struct s3c2440_spi *)S3C2440_SPI_BASE;
}
static inline struct s3c2440_sdi *s3c2440_get_base_sdi(void)
{
    return (struct s3c2440_sdi *)S3C2440_SDI_BASE;
}
#endif /*__S3C2440_H__*/
linux-bsp/asm-study/yaffs2/bsp/s3c_board.c
New file
@@ -0,0 +1,213 @@
#include "s3c_board.h"
#include "s3c2440.h"
unsigned int s3c2440_get_fclk(void)
{
    struct s3c2440_clock_power *clk_power = s3c2440_get_base_clock_power();
    unsigned int r, m, p, s;
    r = clk_power->MPLLCON;
    m = ((r & 0xFF000) >> 12) + 8;
    p = ((r & 0x003F0) >> 4) + 2;
    s = r & 0x3;
    return (SYS_CLK_FREQ * m * 2) / (p << s);
}
unsigned int s3c2440_get_hclk(void)
{
    struct s3c2440_clock_power * const clk_power = s3c2440_get_base_clock_power();
    unsigned int fclk = s3c2440_get_fclk();
    if (clk_power->CLKDIVN & 0x6)
    {
        if ((clk_power->CLKDIVN & 0x6)==2)
            return fclk/2;
        if ((clk_power->CLKDIVN & 0x6)==6)
            return (clk_power->CAMDIVN & 0x100) ? fclk/6 : fclk/3;
        if ((clk_power->CLKDIVN & 0x6)==4)
            return (clk_power->CAMDIVN & 0x200) ? fclk/8 : fclk/4;
        return fclk;
    }
    return fclk;
}
unsigned int s3c2440_get_pclk(void)
{
    struct s3c2440_clock_power * const clk_power = s3c2440_get_base_clock_power();
    unsigned int hclk = s3c2440_get_hclk();
    return (clk_power->CLKDIVN & 0x1) ? hclk/2 : hclk;
}
unsigned int s3c2440_get_uclk(void)
{
    struct s3c2440_clock_power *clk_power = s3c2440_get_base_clock_power();
    unsigned int r, m, p, s;
    r = clk_power->UPLLCON;
    m = ((r & 0xFF000) >> 12) + 8;
    p = ((r & 0x003F0) >> 4) + 2;
    s = r & 0x3;
    return (SYS_CLK_FREQ * m) / (p << s);
}
void s3c2440_set_baudrate(unsigned int baudrate, int index)
{
    struct s3c2440_uart *uart = s3c2440_get_base_uart(index);
    unsigned int reg = 0;
    int i;
    reg = s3c2440_get_pclk() / (16 * baudrate) - 1;
    uart->UBRDIV = reg;
    for (i = 0; i < 100; i++);
}
int s3c2440_serial_init(unsigned int baudrate, int index)
{
    struct s3c2440_uart *uart = s3c2440_get_base_uart(index);
    /* FIFO enable, Tx/Rx FIFO clear */
    uart->UFCON = 0x07;
    uart->UMCON = 0x0;
    /* Normal,No parity,1 stop,8 bit */
    uart->ULCON = 0x3;
    /*
     * tx=level,rx=edge,disable timeout int.,enable rx error int.,
     * normal,interrupt or polling
     */
    uart->UCON = (1<<8) | (1<<2) | (1<<0);
//    uart->UMCON = 0x1; /* RTS up */
    s3c2440_set_baudrate(baudrate, index);
    return (0);
}
int s3c2440_serail_set_afc(int enable, int index)
{
    if (index != S3C2440_UART0 || index != S3C2440_UART1)
        return -1;
    struct s3c2440_uart *uart = s3c2440_get_base_uart(index);
    if (enable) {
        uart->UMCON = (1<<4);
    } else {
        uart->UMCON = 0;
        uart->UMCON = 0;
        uart->UMCON = 0;
        uart->UMCON = 1;
    }
    return 0;
}
/*
 * Read a single byte from the serial port. Returns 1 on success, 0
 * otherwise. When the function is succesfull, the character read is
 * written into its argument c.
 */
int s3c2440_serial_getc (int index)
{
    struct s3c2440_uart *uart = s3c2440_get_base_uart(index);
    /* wait for character to arrive */
    //while (!(uart->UTRSTAT & 0x1));
    while(!(uart->UFSTAT & 0x1F));
    return uart->URXH & 0xff;
}
#if 0
static int hwflow = 0; /* turned off by default */
int hwflow_onoff(int on)
{
    switch(on) {
    case 0:
    default:
        break; /* return current */
    case 1:
        hwflow = 1; /* turn on */
        break;
    case -1:
        hwflow = 0; /* turn off */
        break;
    }
    return hwflow;
}
#endif
#if 0
static int be_quiet = 0;
void disable_putc(void)
{
    be_quiet = 1;
}
void enable_putc(void)
{
    be_quiet = 0;
}
#endif
/*
 * Output a single byte to the serial port.
 */
void s3c2440_serial_putc (char c, int index)
{
    struct s3c2440_uart *uart = s3c2440_get_base_uart(index);
    /* wait for room in the tx FIFO */
    //while ((!(uart->UTRSTAT & 0x2)));
    while (uart->UFSTAT & (1<<14));
    uart->UTXH = c;
}
void s3c2440_serial_puts(const char *s, int index)
{
    while (*s)
    {
        if (*s == '\n')              /*  If \n, also do \r */
            s3c2440_serial_putc('\r', index);
        s3c2440_serial_putc (*s++, index);
    }
}
void s3c2440_interrupt_enable(unsigned int mask)
{
    mask = ~mask;
    struct s3c2440_interrupt *interrupt = s3c2440_get_base_interrupt();
    interrupt->INTMSK &= mask;
}
void s3c2440_interrupt_disable(unsigned int mask)
{
    struct s3c2440_interrupt *interrupt = s3c2440_get_base_interrupt();
    interrupt->INTMSK |= mask;
}
void s3c2440_sub_interrupt_enable(unsigned int mask)
{
    mask = ~mask;
    struct s3c2440_interrupt *interrupt = s3c2440_get_base_interrupt();
    interrupt->INTSUBMSK &= mask;
}
void s3c2440_sub_interrupt_disable(unsigned int mask)
{
    struct s3c2440_interrupt *interrupt = s3c2440_get_base_interrupt();
    interrupt->INTSUBMSK |= mask;
}
linux-bsp/asm-study/yaffs2/bsp/s3c_board.h
New file
@@ -0,0 +1,34 @@
#ifndef __S3C_BOARD_H__
#define __S3C_BOARD_H__
#include "s3c2440.h"
#define SYS_CLK_FREQ             12000000
#define CONSOLE_SERIAL           S3C2440_UART0
#define CONSOLE_BAUDRATE         115200
unsigned int s3c2440_get_fclk(void);
unsigned int s3c2440_get_hclk(void);
unsigned int s3c2440_get_pclk(void);
unsigned int s3c2440_get_uclk(void);
void s3c2440_set_baudrate(unsigned int baudrate, int index);
int s3c2440_serial_init(unsigned int baudrate, int index);
int s3c2440_serail_set_afc(int enable, int index);
int s3c2440_serial_getc (int index);
void s3c2440_serial_putc (char ch, int index);
int s3c2440_serial_tstc(int index);
void s3c2440_serial_puts(const char *s, int index);
#define console_serial_init()      s3c2440_serial_init(CONSOLE_BAUDRATE, CONSOLE_SERIAL)
#define console_serial_getc()      s3c2440_serial_getc(CONSOLE_SERIAL)
#define console_serial_tstc()      s3c2440_serial_tstc(CONSOLE_SERIAL)
#define console_serial_putc(c)     s3c2440_serial_putc(c, CONSOLE_SERIAL)
#define console_serial_puts(s)     s3c2440_serial_puts(s, CONSOLE_SERIAL)
void s3c2440_interrupt_enable(unsigned int mask);
void s3c2440_interrupt_disable(unsigned int mask);
void s3c2440_sub_interrupt_enable(unsigned int mask);
void s3c2440_sub_interrupt_disable(unsigned int mask);
#endif
linux-bsp/asm-study/yaffs2/common/dlmalloc.c
New file
@@ -0,0 +1,3320 @@
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define DEBUG   1
#if 0    /* Moved to malloc.h */
/* ---------- To make a malloc.h, start cutting here ------------ */
/*
  A version of malloc/free/realloc written by Doug Lea and released to the
  public domain.  Send questions/comments/complaints/performance data
  to dl@cs.oswego.edu
* VERSION 2.6.6  Sun Mar  5 19:10:03 2000  Doug Lea  (dl at gee)
   Note: There may be an updated version of this malloc obtainable at
       ftp://g.oswego.edu/pub/misc/malloc.c
     Check before installing!
* Why use this malloc?
  This is not the fastest, most space-conserving, most portable, or
  most tunable malloc ever written. However it is among the fastest
  while also being among the most space-conserving, portable and tunable.
  Consistent balance across these factors results in a good general-purpose
  allocator. For a high-level description, see
     http://g.oswego.edu/dl/html/malloc.html
* Synopsis of public routines
  (Much fuller descriptions are contained in the program documentation below.)
  malloc(size_t n);
     Return a pointer to a newly allocated chunk of at least n bytes, or null
     if no space is available.
  free(Void_t* p);
     Release the chunk of memory pointed to by p, or no effect if p is null.
  realloc(Void_t* p, size_t n);
     Return a pointer to a chunk of size n that contains the same data
     as does chunk p up to the minimum of (n, p's size) bytes, or null
     if no space is available. The returned pointer may or may not be
     the same as p. If p is null, equivalent to malloc.  Unless the
     #define REALLOC_ZERO_BYTES_FREES below is set, realloc with a
     size argument of zero (re)allocates a minimum-sized chunk.
  memalign(size_t alignment, size_t n);
     Return a pointer to a newly allocated chunk of n bytes, aligned
     in accord with the alignment argument, which must be a power of
     two.
  valloc(size_t n);
     Equivalent to memalign(pagesize, n), where pagesize is the page
     size of the system (or as near to this as can be figured out from
     all the includes/defines below.)
  pvalloc(size_t n);
     Equivalent to valloc(minimum-page-that-holds(n)), that is,
     round up n to nearest pagesize.
  calloc(size_t unit, size_t quantity);
     Returns a pointer to quantity * unit bytes, with all locations
     set to zero.
  cfree(Void_t* p);
     Equivalent to free(p).
  malloc_trim(size_t pad);
     Release all but pad bytes of freed top-most memory back
     to the system. Return 1 if successful, else 0.
  malloc_usable_size(Void_t* p);
     Report the number usable allocated bytes associated with allocated
     chunk p. This may or may not report more bytes than were requested,
     due to alignment and minimum size constraints.
  malloc_stats();
     Prints brief summary statistics.
  mallinfo()
     Returns (by copy) a struct containing various summary statistics.
  mallopt(int parameter_number, int parameter_value)
     Changes one of the tunable parameters described below. Returns
     1 if successful in changing the parameter, else 0.
* Vital statistics:
  Alignment:                            8-byte
       8 byte alignment is currently hardwired into the design.  This
       seems to suffice for all current machines and C compilers.
  Assumed pointer representation:       4 or 8 bytes
       Code for 8-byte pointers is untested by me but has worked
       reliably by Wolfram Gloger, who contributed most of the
       changes supporting this.
  Assumed size_t  representation:       4 or 8 bytes
       Note that size_t is allowed to be 4 bytes even if pointers are 8.
  Minimum overhead per allocated chunk: 4 or 8 bytes
       Each malloced chunk has a hidden overhead of 4 bytes holding size
       and status information.
  Minimum allocated size: 4-byte ptrs:  16 bytes    (including 4 overhead)
              8-byte ptrs:  24/32 bytes (including, 4/8 overhead)
       When a chunk is freed, 12 (for 4byte ptrs) or 20 (for 8 byte
       ptrs but 4 byte size) or 24 (for 8/8) additional bytes are
       needed; 4 (8) for a trailing size field
       and 8 (16) bytes for free list pointers. Thus, the minimum
       allocatable size is 16/24/32 bytes.
       Even a request for zero bytes (i.e., malloc(0)) returns a
       pointer to something of the minimum allocatable size.
  Maximum allocated size: 4-byte size_t: 2^31 -  8 bytes
              8-byte size_t: 2^63 - 16 bytes
       It is assumed that (possibly signed) size_t bit values suffice to
       represent chunk sizes. `Possibly signed' is due to the fact
       that `size_t' may be defined on a system as either a signed or
       an unsigned type. To be conservative, values that would appear
       as negative numbers are avoided.
       Requests for sizes with a negative sign bit when the request
       size is treaded as a long will return null.
  Maximum overhead wastage per allocated chunk: normally 15 bytes
       Alignnment demands, plus the minimum allocatable size restriction
       make the normal worst-case wastage 15 bytes (i.e., up to 15
       more bytes will be allocated than were requested in malloc), with
       two exceptions:
     1. Because requests for zero bytes allocate non-zero space,
        the worst case wastage for a request of zero bytes is 24 bytes.
     2. For requests >= mmap_threshold that are serviced via
        mmap(), the worst case wastage is 8 bytes plus the remainder
        from a system page (the minimal mmap unit); typically 4096 bytes.
* Limitations
    Here are some features that are NOT currently supported
    * No user-definable hooks for callbacks and the like.
    * No automated mechanism for fully checking that all accesses
      to malloced memory stay within their bounds.
    * No support for compaction.
* Synopsis of compile-time options:
    People have reported using previous versions of this malloc on all
    versions of Unix, sometimes by tweaking some of the defines
    below. It has been tested most extensively on Solaris and
    Linux. It is also reported to work on WIN32 platforms.
    People have also reported adapting this malloc for use in
    stand-alone embedded systems.
    The implementation is in straight, hand-tuned ANSI C.  Among other
    consequences, it uses a lot of macros.  Because of this, to be at
    all usable, this code should be compiled using an optimizing compiler
    (for example gcc -O2) that can simplify expressions and control
    paths.
  __STD_C                  (default: derived from C compiler defines)
     Nonzero if using ANSI-standard C compiler, a C++ compiler, or
     a C compiler sufficiently close to ANSI to get away with it.
  DEBUG                    (default: NOT defined)
     Define to enable debugging. Adds fairly extensive assertion-based
     checking to help track down memory errors, but noticeably slows down
     execution.
  REALLOC_ZERO_BYTES_FREES (default: NOT defined)
     Define this if you think that realloc(p, 0) should be equivalent
     to free(p). Otherwise, since malloc returns a unique pointer for
     malloc(0), so does realloc(p, 0).
  HAVE_MEMCPY               (default: defined)
     Define if you are not otherwise using ANSI STD C, but still
     have memcpy and memset in your C library and want to use them.
     Otherwise, simple internal versions are supplied.
  USE_MEMCPY               (default: 1 if HAVE_MEMCPY is defined, 0 otherwise)
     Define as 1 if you want the C library versions of memset and
     memcpy called in realloc and calloc (otherwise macro versions are used).
     At least on some platforms, the simple macro versions usually
     outperform libc versions.
  HAVE_MMAP                 (default: defined as 1)
     Define to non-zero to optionally make malloc() use mmap() to
     allocate very large blocks.
  HAVE_MREMAP                 (default: defined as 0 unless Linux libc set)
     Define to non-zero to optionally make realloc() use mremap() to
     reallocate very large blocks.
  malloc_getpagesize        (default: derived from system #includes)
     Either a constant or routine call returning the system page size.
  HAVE_USR_INCLUDE_MALLOC_H (default: NOT defined)
     Optionally define if you are on a system with a /usr/include/malloc.h
     that declares struct mallinfo. It is not at all necessary to
     define this even if you do, but will ensure consistency.
  INTERNAL_SIZE_T           (default: size_t)
     Define to a 32-bit type (probably `unsigned int') if you are on a
     64-bit machine, yet do not want or need to allow malloc requests of
     greater than 2^31 to be handled. This saves space, especially for
     very small chunks.
  INTERNAL_LINUX_C_LIB      (default: NOT defined)
     Defined only when compiled as part of Linux libc.
     Also note that there is some odd internal name-mangling via defines
     (for example, internally, `malloc' is named `mALLOc') needed
     when compiling in this case. These look funny but don't otherwise
     affect anything.
  WIN32                     (default: undefined)
     Define this on MS win (95, nt) platforms to compile in sbrk emulation.
  LACKS_UNISTD_H            (default: undefined if not WIN32)
     Define this if your system does not have a <unistd.h>.
  LACKS_SYS_PARAM_H         (default: undefined if not WIN32)
     Define this if your system does not have a <sys/param.h>.
  MORECORE                  (default: sbrk)
     The name of the routine to call to obtain more memory from the system.
  MORECORE_FAILURE          (default: -1)
     The value returned upon failure of MORECORE.
  MORECORE_CLEARS           (default 1)
     true (1) if the routine mapped to MORECORE zeroes out memory (which
     holds for sbrk).
  DEFAULT_TRIM_THRESHOLD
  DEFAULT_TOP_PAD
  DEFAULT_MMAP_THRESHOLD
  DEFAULT_MMAP_MAX
     Default values of tunable parameters (described in detail below)
     controlling interaction with host system routines (sbrk, mmap, etc).
     These values may also be changed dynamically via mallopt(). The
     preset defaults are those that give best performance for typical
     programs/systems.
  USE_DL_PREFIX             (default: undefined)
     Prefix all public routines with the string 'dl'.  Useful to
     quickly avoid procedure declaration conflicts and linker symbol
     conflicts with existing memory allocation routines.
*/
/* Preliminaries */
#ifndef __STD_C
#ifdef __STDC__
#define __STD_C     1
#else
#if __cplusplus
#define __STD_C     1
#else
#define __STD_C     0
#endif /*__cplusplus*/
#endif /*__STDC__*/
#endif /*__STD_C*/
#ifndef Void_t
#if (__STD_C || defined(WIN32))
#define Void_t      void
#else
#define Void_t      char
#endif
#endif /*Void_t*/
#if __STD_C
#include <stddef.h>   /* for size_t */
#else
#include <sys/types.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>    /* needed for malloc_stats */
/*
  Compile-time options
*/
/*
    Debugging:
    Because freed chunks may be overwritten with link fields, this
    malloc will often die when freed memory is overwritten by user
    programs.  This can be very effective (albeit in an annoying way)
    in helping track down dangling pointers.
    If you compile with -DDEBUG, a number of assertion checks are
    enabled that will catch more memory errors. You probably won't be
    able to make much sense of the actual assertion errors, but they
    should help you locate incorrectly overwritten memory.  The
    checking is fairly extensive, and will slow down execution
    noticeably. Calling malloc_stats or mallinfo with DEBUG set will
    attempt to check every non-mmapped allocated and free chunk in the
    course of computing the summmaries. (By nature, mmapped regions
    cannot be checked very much automatically.)
    Setting DEBUG may also be helpful if you are trying to modify
    this code. The assertions in the check routines spell out in more
    detail the assumptions and invariants underlying the algorithms.
*/
/*
  INTERNAL_SIZE_T is the word-size used for internal bookkeeping
  of chunk sizes. On a 64-bit machine, you can reduce malloc
  overhead by defining INTERNAL_SIZE_T to be a 32 bit `unsigned int'
  at the expense of not being able to handle requests greater than
  2^31. This limitation is hardly ever a concern; you are encouraged
  to set this. However, the default version is the same as size_t.
*/
#ifndef INTERNAL_SIZE_T
#define INTERNAL_SIZE_T size_t
#endif
/*
  REALLOC_ZERO_BYTES_FREES should be set if a call to
  realloc with zero bytes should be the same as a call to free.
  Some people think it should. Otherwise, since this malloc
  returns a unique pointer for malloc(0), so does realloc(p, 0).
*/
/*   #define REALLOC_ZERO_BYTES_FREES */
/*
  WIN32 causes an emulation of sbrk to be compiled in
  mmap-based options are not currently supported in WIN32.
*/
/* #define WIN32 */
#ifdef WIN32
#define MORECORE wsbrk
#define HAVE_MMAP 0
#define LACKS_UNISTD_H
#define LACKS_SYS_PARAM_H
/*
  Include 'windows.h' to get the necessary declarations for the
  Microsoft Visual C++ data structures and routines used in the 'sbrk'
  emulation.
  Define WIN32_LEAN_AND_MEAN so that only the essential Microsoft
  Visual C++ header files are included.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
/*
  HAVE_MEMCPY should be defined if you are not otherwise using
  ANSI STD C, but still have memcpy and memset in your C library
  and want to use them in calloc and realloc. Otherwise simple
  macro versions are defined here.
  USE_MEMCPY should be defined as 1 if you actually want to
  have memset and memcpy called. People report that the macro
  versions are often enough faster than libc versions on many
  systems that it is better to use them.
*/
#define HAVE_MEMCPY
#ifndef USE_MEMCPY
#ifdef HAVE_MEMCPY
#define USE_MEMCPY 1
#else
#define USE_MEMCPY 0
#endif
#endif
#if (__STD_C || defined(HAVE_MEMCPY))
#if __STD_C
void* memset(void*, int, size_t);
void* memcpy(void*, const void*, size_t);
#else
#ifdef WIN32
/* On Win32 platforms, 'memset()' and 'memcpy()' are already declared in */
/* 'windows.h' */
#else
Void_t* memset();
Void_t* memcpy();
#endif
#endif
#endif
#if USE_MEMCPY
/* The following macros are only invoked with (2n+1)-multiples of
   INTERNAL_SIZE_T units, with a positive integer n. This is exploited
   for fast inline execution when n is small. */
#define MALLOC_ZERO(charp, nbytes)                                            \
do {                                                                          \
  INTERNAL_SIZE_T mzsz = (nbytes);                                            \
  if(mzsz <= 9*sizeof(mzsz)) {                                                \
    INTERNAL_SIZE_T* mz = (INTERNAL_SIZE_T*) (charp);                         \
    if(mzsz >= 5*sizeof(mzsz)) {     *mz++ = 0;                               \
                     *mz++ = 0;                               \
      if(mzsz >= 7*sizeof(mzsz)) {   *mz++ = 0;                               \
                     *mz++ = 0;                               \
    if(mzsz >= 9*sizeof(mzsz)) { *mz++ = 0;                               \
                     *mz++ = 0; }}}                           \
                     *mz++ = 0;                               \
                     *mz++ = 0;                               \
                     *mz   = 0;                               \
  } else memset((charp), 0, mzsz);                                            \
} while(0)
#define MALLOC_COPY(dest,src,nbytes)                                          \
do {                                                                          \
  INTERNAL_SIZE_T mcsz = (nbytes);                                            \
  if(mcsz <= 9*sizeof(mcsz)) {                                                \
    INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) (src);                        \
    INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) (dest);                       \
    if(mcsz >= 5*sizeof(mcsz)) {     *mcdst++ = *mcsrc++;                     \
                     *mcdst++ = *mcsrc++;                     \
      if(mcsz >= 7*sizeof(mcsz)) {   *mcdst++ = *mcsrc++;                     \
                     *mcdst++ = *mcsrc++;                     \
    if(mcsz >= 9*sizeof(mcsz)) { *mcdst++ = *mcsrc++;                     \
                     *mcdst++ = *mcsrc++; }}}                 \
                     *mcdst++ = *mcsrc++;                     \
                     *mcdst++ = *mcsrc++;                     \
                     *mcdst   = *mcsrc  ;                     \
  } else memcpy(dest, src, mcsz);                                             \
} while(0)
#else /* !USE_MEMCPY */
/* Use Duff's device for good zeroing/copying performance. */
#define MALLOC_ZERO(charp, nbytes)                                            \
do {                                                                          \
  INTERNAL_SIZE_T* mzp = (INTERNAL_SIZE_T*)(charp);                           \
  long mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T), mcn;                         \
  if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; }             \
  switch (mctmp) {                                                            \
    case 0: for(;;) { *mzp++ = 0;                                             \
    case 7:           *mzp++ = 0;                                             \
    case 6:           *mzp++ = 0;                                             \
    case 5:           *mzp++ = 0;                                             \
    case 4:           *mzp++ = 0;                                             \
    case 3:           *mzp++ = 0;                                             \
    case 2:           *mzp++ = 0;                                             \
    case 1:           *mzp++ = 0; if(mcn <= 0) break; mcn--; }                \
  }                                                                           \
} while(0)
#define MALLOC_COPY(dest,src,nbytes)                                          \
do {                                                                          \
  INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) src;                            \
  INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) dest;                           \
  long mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T), mcn;                         \
  if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; }             \
  switch (mctmp) {                                                            \
    case 0: for(;;) { *mcdst++ = *mcsrc++;                                    \
    case 7:           *mcdst++ = *mcsrc++;                                    \
    case 6:           *mcdst++ = *mcsrc++;                                    \
    case 5:           *mcdst++ = *mcsrc++;                                    \
    case 4:           *mcdst++ = *mcsrc++;                                    \
    case 3:           *mcdst++ = *mcsrc++;                                    \
    case 2:           *mcdst++ = *mcsrc++;                                    \
    case 1:           *mcdst++ = *mcsrc++; if(mcn <= 0) break; mcn--; }       \
  }                                                                           \
} while(0)
#endif
/*
  Define HAVE_MMAP to optionally make malloc() use mmap() to
  allocate very large blocks.  These will be returned to the
  operating system immediately after a free().
*/
#ifndef HAVE_MMAP
#define HAVE_MMAP 1
#endif
/*
  Define HAVE_MREMAP to make realloc() use mremap() to re-allocate
  large blocks.  This is currently only possible on Linux with
  kernel versions newer than 1.3.77.
*/
#ifndef HAVE_MREMAP
#ifdef INTERNAL_LINUX_C_LIB
#define HAVE_MREMAP 1
#else
#define HAVE_MREMAP 0
#endif
#endif
#if HAVE_MMAP
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
#define MAP_ANONYMOUS MAP_ANON
#endif
#endif /* HAVE_MMAP */
/*
  Access to system page size. To the extent possible, this malloc
  manages memory from the system in page-size units.
  The following mechanics for getpagesize were adapted from
  bsd/gnu getpagesize.h
*/
#ifndef LACKS_UNISTD_H
#  include <unistd.h>
#endif
#ifndef malloc_getpagesize
#  ifdef _SC_PAGESIZE         /* some SVR4 systems omit an underscore */
#    ifndef _SC_PAGE_SIZE
#      define _SC_PAGE_SIZE _SC_PAGESIZE
#    endif
#  endif
#  ifdef _SC_PAGE_SIZE
#    define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
#  else
#    if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
       extern size_t getpagesize();
#      define malloc_getpagesize getpagesize()
#    else
#      ifdef WIN32
#        define malloc_getpagesize (4096) /* TBD: Use 'GetSystemInfo' instead */
#      else
#        ifndef LACKS_SYS_PARAM_H
#          include <sys/param.h>
#        endif
#        ifdef EXEC_PAGESIZE
#          define malloc_getpagesize EXEC_PAGESIZE
#        else
#          ifdef NBPG
#            ifndef CLSIZE
#              define malloc_getpagesize NBPG
#            else
#              define malloc_getpagesize (NBPG * CLSIZE)
#            endif
#          else
#            ifdef NBPC
#              define malloc_getpagesize NBPC
#            else
#              ifdef PAGESIZE
#                define malloc_getpagesize PAGESIZE
#              else
#                define malloc_getpagesize (4096) /* just guess */
#              endif
#            endif
#          endif
#        endif
#      endif
#    endif
#  endif
#endif
/*
  This version of malloc supports the standard SVID/XPG mallinfo
  routine that returns a struct containing the same kind of
  information you can get from malloc_stats. It should work on
  any SVID/XPG compliant system that has a /usr/include/malloc.h
  defining struct mallinfo. (If you'd like to install such a thing
  yourself, cut out the preliminary declarations as described above
  and below and save them in a malloc.h file. But there's no
  compelling reason to bother to do this.)
  The main declaration needed is the mallinfo struct that is returned
  (by-copy) by mallinfo().  The SVID/XPG malloinfo struct contains a
  bunch of fields, most of which are not even meaningful in this
  version of malloc. Some of these fields are are instead filled by
  mallinfo() with other numbers that might possibly be of interest.
  HAVE_USR_INCLUDE_MALLOC_H should be set if you have a
  /usr/include/malloc.h file that includes a declaration of struct
  mallinfo.  If so, it is included; else an SVID2/XPG2 compliant
  version is declared below.  These must be precisely the same for
  mallinfo() to work.
*/
/* #define HAVE_USR_INCLUDE_MALLOC_H */
#if HAVE_USR_INCLUDE_MALLOC_H
#include "/usr/include/malloc.h"
#else
/* SVID2/XPG mallinfo structure */
struct mallinfo {
  int arena;    /* total space allocated from system */
  int ordblks;  /* number of non-inuse chunks */
  int smblks;   /* unused -- always zero */
  int hblks;    /* number of mmapped regions */
  int hblkhd;   /* total space in mmapped regions */
  int usmblks;  /* unused -- always zero */
  int fsmblks;  /* unused -- always zero */
  int uordblks; /* total allocated space */
  int fordblks; /* total non-inuse space */
  int keepcost; /* top-most, releasable (via malloc_trim) space */
};
/* SVID2/XPG mallopt options */
#define M_MXFAST  1    /* UNUSED in this malloc */
#define M_NLBLKS  2    /* UNUSED in this malloc */
#define M_GRAIN   3    /* UNUSED in this malloc */
#define M_KEEP    4    /* UNUSED in this malloc */
#endif
/* mallopt options that actually do something */
#define M_TRIM_THRESHOLD    -1
#define M_TOP_PAD           -2
#define M_MMAP_THRESHOLD    -3
#define M_MMAP_MAX          -4
#ifndef DEFAULT_TRIM_THRESHOLD
#define DEFAULT_TRIM_THRESHOLD (128 * 1024)
#endif
/*
    M_TRIM_THRESHOLD is the maximum amount of unused top-most memory
      to keep before releasing via malloc_trim in free().
      Automatic trimming is mainly useful in long-lived programs.
      Because trimming via sbrk can be slow on some systems, and can
      sometimes be wasteful (in cases where programs immediately
      afterward allocate more large chunks) the value should be high
      enough so that your overall system performance would improve by
      releasing.
      The trim threshold and the mmap control parameters (see below)
      can be traded off with one another. Trimming and mmapping are
      two different ways of releasing unused memory back to the
      system. Between these two, it is often possible to keep
      system-level demands of a long-lived program down to a bare
      minimum. For example, in one test suite of sessions measuring
      the XF86 X server on Linux, using a trim threshold of 128K and a
      mmap threshold of 192K led to near-minimal long term resource
      consumption.
      If you are using this malloc in a long-lived program, it should
      pay to experiment with these values.  As a rough guide, you
      might set to a value close to the average size of a process
      (program) running on your system.  Releasing this much memory
      would allow such a process to run in memory.  Generally, it's
      worth it to tune for trimming rather tham memory mapping when a
      program undergoes phases where several large chunks are
      allocated and released in ways that can reuse each other's
      storage, perhaps mixed with phases where there are no such
      chunks at all.  And in well-behaved long-lived programs,
      controlling release of large blocks via trimming versus mapping
      is usually faster.
      However, in most programs, these parameters serve mainly as
      protection against the system-level effects of carrying around
      massive amounts of unneeded memory. Since frequent calls to
      sbrk, mmap, and munmap otherwise degrade performance, the default
      parameters are set to relatively high values that serve only as
      safeguards.
      The default trim value is high enough to cause trimming only in
      fairly extreme (by current memory consumption standards) cases.
      It must be greater than page size to have any useful effect.  To
      disable trimming completely, you can set to (unsigned long)(-1);
*/
#ifndef DEFAULT_TOP_PAD
#define DEFAULT_TOP_PAD        (0)
#endif
/*
    M_TOP_PAD is the amount of extra `padding' space to allocate or
      retain whenever sbrk is called. It is used in two ways internally:
      * When sbrk is called to extend the top of the arena to satisfy
    a new malloc request, this much padding is added to the sbrk
    request.
      * When malloc_trim is called automatically from free(),
    it is used as the `pad' argument.
      In both cases, the actual amount of padding is rounded
      so that the end of the arena is always a system page boundary.
      The main reason for using padding is to avoid calling sbrk so
      often. Having even a small pad greatly reduces the likelihood
      that nearly every malloc request during program start-up (or
      after trimming) will invoke sbrk, which needlessly wastes
      time.
      Automatic rounding-up to page-size units is normally sufficient
      to avoid measurable overhead, so the default is 0.  However, in
      systems where sbrk is relatively slow, it can pay to increase
      this value, at the expense of carrying around more memory than
      the program needs.
*/
#ifndef DEFAULT_MMAP_THRESHOLD
#define DEFAULT_MMAP_THRESHOLD (128 * 1024)
#endif
/*
    M_MMAP_THRESHOLD is the request size threshold for using mmap()
      to service a request. Requests of at least this size that cannot
      be allocated using already-existing space will be serviced via mmap.
      (If enough normal freed space already exists it is used instead.)
      Using mmap segregates relatively large chunks of memory so that
      they can be individually obtained and released from the host
      system. A request serviced through mmap is never reused by any
      other request (at least not directly; the system may just so
      happen to remap successive requests to the same locations).
      Segregating space in this way has the benefit that mmapped space
      can ALWAYS be individually released back to the system, which
      helps keep the system level memory demands of a long-lived
      program low. Mapped memory can never become `locked' between
      other chunks, as can happen with normally allocated chunks, which
      menas that even trimming via malloc_trim would not release them.
      However, it has the disadvantages that:
     1. The space cannot be reclaimed, consolidated, and then
        used to service later requests, as happens with normal chunks.
     2. It can lead to more wastage because of mmap page alignment
        requirements
     3. It causes malloc performance to be more dependent on host
        system memory management support routines which may vary in
        implementation quality and may impose arbitrary
        limitations. Generally, servicing a request via normal
        malloc steps is faster than going through a system's mmap.
      All together, these considerations should lead you to use mmap
      only for relatively large requests.
*/
#ifndef DEFAULT_MMAP_MAX
#if HAVE_MMAP
#define DEFAULT_MMAP_MAX       (64)
#else
#define DEFAULT_MMAP_MAX       (0)
#endif
#endif
/*
    M_MMAP_MAX is the maximum number of requests to simultaneously
      service using mmap. This parameter exists because:
     1. Some systems have a limited number of internal tables for
        use by mmap.
     2. In most systems, overreliance on mmap can degrade overall
        performance.
     3. If a program allocates many large regions, it is probably
        better off using normal sbrk-based allocation routines that
        can reclaim and reallocate normal heap memory. Using a
        small value allows transition into this mode after the
        first few allocations.
      Setting to 0 disables all use of mmap.  If HAVE_MMAP is not set,
      the default value is 0, and attempts to set it to non-zero values
      in mallopt will fail.
*/
/*
    USE_DL_PREFIX will prefix all public routines with the string 'dl'.
      Useful to quickly avoid procedure declaration conflicts and linker
      symbol conflicts with existing memory allocation routines.
*/
/* #define USE_DL_PREFIX */
/*
  Special defines for linux libc
  Except when compiled using these special defines for Linux libc
  using weak aliases, this malloc is NOT designed to work in
  multithreaded applications.  No semaphores or other concurrency
  control are provided to ensure that multiple malloc or free calls
  don't run at the same time, which could be disasterous. A single
  semaphore could be used across malloc, realloc, and free (which is
  essentially the effect of the linux weak alias approach). It would
  be hard to obtain finer granularity.
*/
#ifdef INTERNAL_LINUX_C_LIB
#if __STD_C
Void_t * __default_morecore_init (ptrdiff_t);
Void_t *(*__morecore)(ptrdiff_t) = __default_morecore_init;
#else
Void_t * __default_morecore_init ();
Void_t *(*__morecore)() = __default_morecore_init;
#endif
#define MORECORE (*__morecore)
#define MORECORE_FAILURE 0
#define MORECORE_CLEARS 1
#else /* INTERNAL_LINUX_C_LIB */
#if __STD_C
extern Void_t*     sbrk(ptrdiff_t);
#else
extern Void_t*     sbrk();
#endif
#ifndef MORECORE
#define MORECORE sbrk
#endif
#ifndef MORECORE_FAILURE
#define MORECORE_FAILURE -1
#endif
#ifndef MORECORE_CLEARS
#define MORECORE_CLEARS 1
#endif
#endif /* INTERNAL_LINUX_C_LIB */
#if defined(INTERNAL_LINUX_C_LIB) && defined(__ELF__)
#define cALLOc        __libc_calloc
#define fREe        __libc_free
#define mALLOc        __libc_malloc
#define mEMALIGn    __libc_memalign
#define rEALLOc        __libc_realloc
#define vALLOc        __libc_valloc
#define pvALLOc        __libc_pvalloc
#define mALLINFo    __libc_mallinfo
#define mALLOPt        __libc_mallopt
#pragma weak calloc = __libc_calloc
#pragma weak free = __libc_free
#pragma weak cfree = __libc_free
#pragma weak malloc = __libc_malloc
#pragma weak memalign = __libc_memalign
#pragma weak realloc = __libc_realloc
#pragma weak valloc = __libc_valloc
#pragma weak pvalloc = __libc_pvalloc
#pragma weak mallinfo = __libc_mallinfo
#pragma weak mallopt = __libc_mallopt
#else
#ifdef USE_DL_PREFIX
#define cALLOc        dlcalloc
#define fREe        dlfree
#define mALLOc        dlmalloc
#define mEMALIGn    dlmemalign
#define rEALLOc        dlrealloc
#define vALLOc        dlvalloc
#define pvALLOc        dlpvalloc
#define mALLINFo    dlmallinfo
#define mALLOPt        dlmallopt
#else /* USE_DL_PREFIX */
#define cALLOc        calloc
#define fREe        free
#define mALLOc        malloc
#define mEMALIGn    memalign
#define rEALLOc        realloc
#define vALLOc        valloc
#define pvALLOc        pvalloc
#define mALLINFo    mallinfo
#define mALLOPt        mallopt
#endif /* USE_DL_PREFIX */
#endif
/* Public routines */
#if __STD_C
Void_t* mALLOc(size_t);
void    fREe(Void_t*);
Void_t* rEALLOc(Void_t*, size_t);
Void_t* mEMALIGn(size_t, size_t);
Void_t* vALLOc(size_t);
Void_t* pvALLOc(size_t);
Void_t* cALLOc(size_t, size_t);
void    cfree(Void_t*);
int     malloc_trim(size_t);
size_t  malloc_usable_size(Void_t*);
void    malloc_stats();
int     mALLOPt(int, int);
struct mallinfo mALLINFo(void);
#else
Void_t* mALLOc();
void    fREe();
Void_t* rEALLOc();
Void_t* mEMALIGn();
Void_t* vALLOc();
Void_t* pvALLOc();
Void_t* cALLOc();
void    cfree();
int     malloc_trim();
size_t  malloc_usable_size();
void    malloc_stats();
int     mALLOPt();
struct mallinfo mALLINFo();
#endif
#ifdef __cplusplus
};  /* end of extern "C" */
#endif
/* ---------- To make a malloc.h, end cutting here ------------ */
#endif    /* 0 */            /* Moved to malloc.h */
#include <malloc.h>
#ifdef DEBUG
#if __STD_C
static void malloc_update_mallinfo (void);
void malloc_stats (void);
#else
static void malloc_update_mallinfo ();
void malloc_stats();
#endif
#endif    /* DEBUG */
/*
  Emulation of sbrk for WIN32
  All code within the ifdef WIN32 is untested by me.
  Thanks to Martin Fong and others for supplying this.
*/
#ifdef WIN32
#define AlignPage(add) (((add) + (malloc_getpagesize-1)) & \
~(malloc_getpagesize-1))
#define AlignPage64K(add) (((add) + (0x10000 - 1)) & ~(0x10000 - 1))
/* resrve 64MB to insure large contiguous space */
#define RESERVED_SIZE (1024*1024*64)
#define NEXT_SIZE (2048*1024)
#define TOP_MEMORY ((unsigned long)2*1024*1024*1024)
struct GmListElement;
typedef struct GmListElement GmListElement;
struct GmListElement
{
    GmListElement* next;
    void* base;
};
static GmListElement* head = 0;
static unsigned int gNextAddress = 0;
static unsigned int gAddressBase = 0;
static unsigned int gAllocatedSize = 0;
static
GmListElement* makeGmListElement (void* bas)
{
    GmListElement* this;
    this = (GmListElement*)(void*)LocalAlloc (0, sizeof (GmListElement));
    assert (this);
    if (this)
    {
        this->base = bas;
        this->next = head;
        head = this;
    }
    return this;
}
void gcleanup ()
{
    BOOL rval;
    assert ( (head == NULL) || (head->base == (void*)gAddressBase));
    if (gAddressBase && (gNextAddress - gAddressBase))
    {
        rval = VirtualFree ((void*)gAddressBase,
                            gNextAddress - gAddressBase,
                            MEM_DECOMMIT);
    assert (rval);
    }
    while (head)
    {
        GmListElement* next = head->next;
        rval = VirtualFree (head->base, 0, MEM_RELEASE);
        assert (rval);
        LocalFree (head);
        head = next;
    }
}
static
void* findRegion (void* start_address, unsigned long size)
{
    MEMORY_BASIC_INFORMATION info;
    if (size >= TOP_MEMORY) return NULL;
    while ((unsigned long)start_address + size < TOP_MEMORY)
    {
        VirtualQuery (start_address, &info, sizeof (info));
        if ((info.State == MEM_FREE) && (info.RegionSize >= size))
            return start_address;
        else
        {
            /* Requested region is not available so see if the */
            /* next region is available.  Set 'start_address' */
            /* to the next region and call 'VirtualQuery()' */
            /* again. */
            start_address = (char*)info.BaseAddress + info.RegionSize;
            /* Make sure we start looking for the next region */
            /* on the *next* 64K boundary.  Otherwise, even if */
            /* the new region is free according to */
            /* 'VirtualQuery()', the subsequent call to */
            /* 'VirtualAlloc()' (which follows the call to */
            /* this routine in 'wsbrk()') will round *down* */
            /* the requested address to a 64K boundary which */
            /* we already know is an address in the */
            /* unavailable region.  Thus, the subsequent call */
            /* to 'VirtualAlloc()' will fail and bring us back */
            /* here, causing us to go into an infinite loop. */
            start_address =
                (void *) AlignPage64K((unsigned long) start_address);
        }
    }
    return NULL;
}
void* wsbrk (long size)
{
    void* tmp;
    if (size > 0)
    {
        if (gAddressBase == 0)
        {
            gAllocatedSize = max (RESERVED_SIZE, AlignPage (size));
            gNextAddress = gAddressBase =
                (unsigned int)VirtualAlloc (NULL, gAllocatedSize,
                                            MEM_RESERVE, PAGE_NOACCESS);
        } else if (AlignPage (gNextAddress + size) > (gAddressBase +
gAllocatedSize))
        {
            long new_size = max (NEXT_SIZE, AlignPage (size));
            void* new_address = (void*)(gAddressBase+gAllocatedSize);
            do
            {
                new_address = findRegion (new_address, new_size);
                if (new_address == 0)
                    return (void*)-1;
                gAddressBase = gNextAddress =
                    (unsigned int)VirtualAlloc (new_address, new_size,
                                                MEM_RESERVE, PAGE_NOACCESS);
                /* repeat in case of race condition */
                /* The region that we found has been snagged */
                /* by another thread */
            }
            while (gAddressBase == 0);
            assert (new_address == (void*)gAddressBase);
            gAllocatedSize = new_size;
            if (!makeGmListElement ((void*)gAddressBase))
                return (void*)-1;
        }
        if ((size + gNextAddress) > AlignPage (gNextAddress))
        {
            void* res;
            res = VirtualAlloc ((void*)AlignPage (gNextAddress),
                                (size + gNextAddress -
                                 AlignPage (gNextAddress)),
                                MEM_COMMIT, PAGE_READWRITE);
            if (res == 0)
                return (void*)-1;
        }
        tmp = (void*)gNextAddress;
        gNextAddress = (unsigned int)tmp + size;
        return tmp;
    }
    else if (size < 0)
    {
        unsigned int alignedGoal = AlignPage (gNextAddress + size);
        /* Trim by releasing the virtual memory */
        if (alignedGoal >= gAddressBase)
        {
            VirtualFree ((void*)alignedGoal, gNextAddress - alignedGoal,
                         MEM_DECOMMIT);
            gNextAddress = gNextAddress + size;
            return (void*)gNextAddress;
        }
        else
        {
            VirtualFree ((void*)gAddressBase, gNextAddress - gAddressBase,
                         MEM_DECOMMIT);
            gNextAddress = gAddressBase;
            return (void*)-1;
        }
    }
    else
    {
        return (void*)gNextAddress;
    }
}
#endif
/*
  Type declarations
*/
struct malloc_chunk
{
  INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */
  INTERNAL_SIZE_T size;      /* Size in bytes, including overhead. */
  struct malloc_chunk* fd;   /* double links -- used only if free. */
  struct malloc_chunk* bk;
} __attribute__((__may_alias__)) ;
typedef struct malloc_chunk* mchunkptr;
/*
   malloc_chunk details:
    (The following includes lightly edited explanations by Colin Plumb.)
    Chunks of memory are maintained using a `boundary tag' method as
    described in e.g., Knuth or Standish.  (See the paper by Paul
    Wilson ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a
    survey of such techniques.)  Sizes of free chunks are stored both
    in the front of each chunk and at the end.  This makes
    consolidating fragmented chunks into bigger chunks very fast.  The
    size fields also hold bits representing whether chunks are free or
    in use.
    An allocated chunk looks like this:
    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |             Size of previous chunk, if allocated            | |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |             Size of chunk, in bytes                         |P|
      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |             User data starts here...                          .
        .                                                               .
        .             (malloc_usable_space() bytes)                     .
        .                                                               |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |             Size of chunk                                     |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    Where "chunk" is the front of the chunk for the purpose of most of
    the malloc code, but "mem" is the pointer that is returned to the
    user.  "Nextchunk" is the beginning of the next contiguous chunk.
    Chunks always begin on even word boundries, so the mem portion
    (which is returned to the user) is also on an even word boundary, and
    thus double-word aligned.
    Free chunks are stored in circular doubly-linked lists, and look like this:
    chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |             Size of previous chunk                            |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    `head:' |             Size of chunk, in bytes                         |P|
      mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |             Forward pointer to next chunk in list             |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |             Back pointer to previous chunk in list            |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |             Unused space (may be 0 bytes long)                .
        .                                                               .
        .                                                               |
nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    `foot:' |             Size of chunk, in bytes                           |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    The P (PREV_INUSE) bit, stored in the unused low-order bit of the
    chunk size (which is always a multiple of two words), is an in-use
    bit for the *previous* chunk.  If that bit is *clear*, then the
    word before the current chunk size contains the previous chunk
    size, and can be used to find the front of the previous chunk.
    (The very first chunk allocated always has this bit set,
    preventing access to non-existent (or non-owned) memory.)
    Note that the `foot' of the current chunk is actually represented
    as the prev_size of the NEXT chunk. (This makes it easier to
    deal with alignments etc).
    The two exceptions to all this are
     1. The special chunk `top', which doesn't bother using the
    trailing size field since there is no
    next contiguous chunk that would have to index off it. (After
    initialization, `top' is forced to always exist.  If it would
    become less than MINSIZE bytes long, it is replenished via
    malloc_extend_top.)
     2. Chunks allocated via mmap, which have the second-lowest-order
    bit (IS_MMAPPED) set in their size fields.  Because they are
    never merged or traversed from any other chunk, they have no
    foot size or inuse information.
    Available chunks are kept in any of several places (all declared below):
    * `av': An array of chunks serving as bin headers for consolidated
       chunks. Each bin is doubly linked.  The bins are approximately
       proportionally (log) spaced.  There are a lot of these bins
       (128). This may look excessive, but works very well in
       practice.  All procedures maintain the invariant that no
       consolidated chunk physically borders another one. Chunks in
       bins are kept in size order, with ties going to the
       approximately least recently used chunk.
       The chunks in each bin are maintained in decreasing sorted order by
       size.  This is irrelevant for the small bins, which all contain
       the same-sized chunks, but facilitates best-fit allocation for
       larger chunks. (These lists are just sequential. Keeping them in
       order almost never requires enough traversal to warrant using
       fancier ordered data structures.)  Chunks of the same size are
       linked with the most recently freed at the front, and allocations
       are taken from the back.  This results in LRU or FIFO allocation
       order, which tends to give each chunk an equal opportunity to be
       consolidated with adjacent freed chunks, resulting in larger free
       chunks and less fragmentation.
    * `top': The top-most available chunk (i.e., the one bordering the
       end of available memory) is treated specially. It is never
       included in any bin, is used only if no other chunk is
       available, and is released back to the system if it is very
       large (see M_TRIM_THRESHOLD).
    * `last_remainder': A bin holding only the remainder of the
       most recently split (non-top) chunk. This bin is checked
       before other non-fitting chunks, so as to provide better
       locality for runs of sequentially allocated chunks.
    *  Implicitly, through the host system's memory mapping tables.
       If supported, requests greater than a threshold are usually
       serviced via calls to mmap, and then later released via munmap.
*/
/*  sizes, alignments */
#define SIZE_SZ                (sizeof(INTERNAL_SIZE_T))
#define MALLOC_ALIGNMENT       (SIZE_SZ + SIZE_SZ)
#define MALLOC_ALIGN_MASK      (MALLOC_ALIGNMENT - 1)
#define MINSIZE                (sizeof(struct malloc_chunk))
/* conversion from malloc headers to user pointers, and back */
#define chunk2mem(p)   ((Void_t*)((char*)(p) + 2*SIZE_SZ))
#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - 2*SIZE_SZ))
/* pad request bytes into a usable size */
#define request2size(req) \
 (((long)((req) + (SIZE_SZ + MALLOC_ALIGN_MASK)) < \
  (long)(MINSIZE + MALLOC_ALIGN_MASK)) ? MINSIZE : \
   (((req) + (SIZE_SZ + MALLOC_ALIGN_MASK)) & ~(MALLOC_ALIGN_MASK)))
/* Check if m has acceptable alignment */
#define aligned_OK(m)    (((unsigned long)((m)) & (MALLOC_ALIGN_MASK)) == 0)
/*
  Physical chunk operations
*/
/* size field is or'ed with PREV_INUSE when previous adjacent chunk in use */
#define PREV_INUSE 0x1
/* size field is or'ed with IS_MMAPPED if the chunk was obtained with mmap() */
#define IS_MMAPPED 0x2
/* Bits to mask off when extracting size */
#define SIZE_BITS (PREV_INUSE|IS_MMAPPED)
/* Ptr to next physical malloc_chunk. */
#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->size & ~PREV_INUSE) ))
/* Ptr to previous physical malloc_chunk */
#define prev_chunk(p)\
   ((mchunkptr)( ((char*)(p)) - ((p)->prev_size) ))
/* Treat space at ptr + offset as a chunk */
#define chunk_at_offset(p, s)  ((mchunkptr)(((char*)(p)) + (s)))
/*
  Dealing with use bits
*/
/* extract p's inuse bit */
#define inuse(p)\
((((mchunkptr)(((char*)(p))+((p)->size & ~PREV_INUSE)))->size) & PREV_INUSE)
/* extract inuse bit of previous chunk */
#define prev_inuse(p)  ((p)->size & PREV_INUSE)
/* check for mmap()'ed chunk */
#define chunk_is_mmapped(p) ((p)->size & IS_MMAPPED)
/* set/clear chunk as in use without otherwise disturbing */
#define set_inuse(p)\
((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size |= PREV_INUSE
#define clear_inuse(p)\
((mchunkptr)(((char*)(p)) + ((p)->size & ~PREV_INUSE)))->size &= ~(PREV_INUSE)
/* check/set/clear inuse bits in known places */
#define inuse_bit_at_offset(p, s)\
 (((mchunkptr)(((char*)(p)) + (s)))->size & PREV_INUSE)
#define set_inuse_bit_at_offset(p, s)\
 (((mchunkptr)(((char*)(p)) + (s)))->size |= PREV_INUSE)
#define clear_inuse_bit_at_offset(p, s)\
 (((mchunkptr)(((char*)(p)) + (s)))->size &= ~(PREV_INUSE))
/*
  Dealing with size fields
*/
/* Get size, ignoring use bits */
#define chunksize(p)          ((p)->size & ~(SIZE_BITS))
/* Set size at head, without disturbing its use bit */
#define set_head_size(p, s)   ((p)->size = (((p)->size & PREV_INUSE) | (s)))
/* Set size/use ignoring previous bits in header */
#define set_head(p, s)        ((p)->size = (s))
/* Set size at footer (only when chunk is not in use) */
#define set_foot(p, s)   (((mchunkptr)((char*)(p) + (s)))->prev_size = (s))
/*
   Bins
    The bins, `av_' are an array of pairs of pointers serving as the
    heads of (initially empty) doubly-linked lists of chunks, laid out
    in a way so that each pair can be treated as if it were in a
    malloc_chunk. (This way, the fd/bk offsets for linking bin heads
    and chunks are the same).
    Bins for sizes < 512 bytes contain chunks of all the same size, spaced
    8 bytes apart. Larger bins are approximately logarithmically
    spaced. (See the table below.) The `av_' array is never mentioned
    directly in the code, but instead via bin access macros.
    Bin layout:
    64 bins of size       8
    32 bins of size      64
    16 bins of size     512
     8 bins of size    4096
     4 bins of size   32768
     2 bins of size  262144
     1 bin  of size what's left
    There is actually a little bit of slop in the numbers in bin_index
    for the sake of speed. This makes no difference elsewhere.
    The special chunks `top' and `last_remainder' get their own bins,
    (this is implemented via yet more trickery with the av_ array),
    although `top' is never properly linked to its bin since it is
    always handled specially.
*/
#define NAV             128   /* number of bins */
typedef struct malloc_chunk* mbinptr;
/* access macros */
#define bin_at(i)      ((mbinptr)((char*)&(av_[2*(i) + 2]) - 2*SIZE_SZ))
#define next_bin(b)    ((mbinptr)((char*)(b) + 2 * sizeof(mbinptr)))
#define prev_bin(b)    ((mbinptr)((char*)(b) - 2 * sizeof(mbinptr)))
/*
   The first 2 bins are never indexed. The corresponding av_ cells are instead
   used for bookkeeping. This is not to save space, but to simplify
   indexing, maintain locality, and avoid some initialization tests.
*/
#define top            (av_[2])          /* The topmost chunk */
#define last_remainder (bin_at(1))       /* remainder from last split */
/*
   Because top initially points to its own bin with initial
   zero size, thus forcing extension on the first malloc request,
   we avoid having any special code in malloc to check whether
   it even exists yet. But we still need to in malloc_extend_top.
*/
#define initial_top    ((mchunkptr)(bin_at(0)))
/* Helper macro to initialize bins */
#define IAV(i)  bin_at(i), bin_at(i)
static mbinptr av_[NAV * 2 + 2] = {
 NULL, NULL,
 IAV(0),   IAV(1),   IAV(2),   IAV(3),   IAV(4),   IAV(5),   IAV(6),   IAV(7),
 IAV(8),   IAV(9),   IAV(10),  IAV(11),  IAV(12),  IAV(13),  IAV(14),  IAV(15),
 IAV(16),  IAV(17),  IAV(18),  IAV(19),  IAV(20),  IAV(21),  IAV(22),  IAV(23),
 IAV(24),  IAV(25),  IAV(26),  IAV(27),  IAV(28),  IAV(29),  IAV(30),  IAV(31),
 IAV(32),  IAV(33),  IAV(34),  IAV(35),  IAV(36),  IAV(37),  IAV(38),  IAV(39),
 IAV(40),  IAV(41),  IAV(42),  IAV(43),  IAV(44),  IAV(45),  IAV(46),  IAV(47),
 IAV(48),  IAV(49),  IAV(50),  IAV(51),  IAV(52),  IAV(53),  IAV(54),  IAV(55),
 IAV(56),  IAV(57),  IAV(58),  IAV(59),  IAV(60),  IAV(61),  IAV(62),  IAV(63),
 IAV(64),  IAV(65),  IAV(66),  IAV(67),  IAV(68),  IAV(69),  IAV(70),  IAV(71),
 IAV(72),  IAV(73),  IAV(74),  IAV(75),  IAV(76),  IAV(77),  IAV(78),  IAV(79),
 IAV(80),  IAV(81),  IAV(82),  IAV(83),  IAV(84),  IAV(85),  IAV(86),  IAV(87),
 IAV(88),  IAV(89),  IAV(90),  IAV(91),  IAV(92),  IAV(93),  IAV(94),  IAV(95),
 IAV(96),  IAV(97),  IAV(98),  IAV(99),  IAV(100), IAV(101), IAV(102), IAV(103),
 IAV(104), IAV(105), IAV(106), IAV(107), IAV(108), IAV(109), IAV(110), IAV(111),
 IAV(112), IAV(113), IAV(114), IAV(115), IAV(116), IAV(117), IAV(118), IAV(119),
 IAV(120), IAV(121), IAV(122), IAV(123), IAV(124), IAV(125), IAV(126), IAV(127)
};
ulong mem_malloc_start = 0;
ulong mem_malloc_end = 0;
ulong mem_malloc_brk = 0;
void *sbrk(ptrdiff_t increment)
{
    ulong old = mem_malloc_brk;
    ulong new = old + increment;
    /*
     * if we are giving memory back make sure we clear it out since
     * we set MORECORE_CLEARS to 1
     */
    if (increment < 0)
        memset((void *)new, 0, -increment);
    if ((new < mem_malloc_start) || (new > mem_malloc_end))
        return (void *)MORECORE_FAILURE;
    mem_malloc_brk = new;
    return (void *)old;
}
void mem_malloc_init(ulong start, ulong size)
{
    mem_malloc_start = start;
    mem_malloc_end = start + size;
    mem_malloc_brk = start;
    memset((void *)mem_malloc_start, 0, size);
    printf("malloc memory space: 0x%lx~0x%lx\n", start, start+size);
}
/* field-extraction macros */
#define first(b) ((b)->fd)
#define last(b)  ((b)->bk)
/*
  Indexing into bins
*/
#define bin_index(sz)                                                          \
(((((unsigned long)(sz)) >> 9) ==    0) ?       (((unsigned long)(sz)) >>  3): \
 ((((unsigned long)(sz)) >> 9) <=    4) ?  56 + (((unsigned long)(sz)) >>  6): \
 ((((unsigned long)(sz)) >> 9) <=   20) ?  91 + (((unsigned long)(sz)) >>  9): \
 ((((unsigned long)(sz)) >> 9) <=   84) ? 110 + (((unsigned long)(sz)) >> 12): \
 ((((unsigned long)(sz)) >> 9) <=  340) ? 119 + (((unsigned long)(sz)) >> 15): \
 ((((unsigned long)(sz)) >> 9) <= 1364) ? 124 + (((unsigned long)(sz)) >> 18): \
                      126)
/*
  bins for chunks < 512 are all spaced 8 bytes apart, and hold
  identically sized chunks. This is exploited in malloc.
*/
#define MAX_SMALLBIN         63
#define MAX_SMALLBIN_SIZE   512
#define SMALLBIN_WIDTH        8
#define smallbin_index(sz)  (((unsigned long)(sz)) >> 3)
/*
   Requests are `small' if both the corresponding and the next bin are small
*/
#define is_small_request(nb) (nb < MAX_SMALLBIN_SIZE - SMALLBIN_WIDTH)
/*
    To help compensate for the large number of bins, a one-level index
    structure is used for bin-by-bin searching.  `binblocks' is a
    one-word bitvector recording whether groups of BINBLOCKWIDTH bins
    have any (possibly) non-empty bins, so they can be skipped over
    all at once during during traversals. The bits are NOT always
    cleared as soon as all bins in a block are empty, but instead only
    when all are noticed to be empty during traversal in malloc.
*/
#define BINBLOCKWIDTH     4   /* bins per block */
#define binblocks_r     ((INTERNAL_SIZE_T)av_[1]) /* bitvector of nonempty blocks */
#define binblocks_w     (av_[1])
/* bin<->block macros */
#define idx2binblock(ix)    ((unsigned)1 << (ix / BINBLOCKWIDTH))
#define mark_binblock(ii)   (binblocks_w = (mbinptr)(binblocks_r | idx2binblock(ii)))
#define clear_binblock(ii)  (binblocks_w = (mbinptr)(binblocks_r & ~(idx2binblock(ii))))
/*  Other static bookkeeping data */
/* variables holding tunable values */
static unsigned long trim_threshold   = DEFAULT_TRIM_THRESHOLD;
static unsigned long top_pad          = DEFAULT_TOP_PAD;
static unsigned int  n_mmaps_max      = DEFAULT_MMAP_MAX;
static unsigned long mmap_threshold   = DEFAULT_MMAP_THRESHOLD;
/* The first value returned from sbrk */
static char* sbrk_base = (char*)(-1);
/* The maximum memory obtained from system via sbrk */
static unsigned long max_sbrked_mem = 0;
/* The maximum via either sbrk or mmap */
static unsigned long max_total_mem = 0;
/* internal working copy of mallinfo */
static struct mallinfo current_mallinfo = {  0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
/* The total memory obtained from system via sbrk */
#define sbrked_mem  (current_mallinfo.arena)
/* Tracking mmaps */
#ifdef DEBUG
static unsigned int n_mmaps = 0;
#endif    /* DEBUG */
static unsigned long mmapped_mem = 0;
#if HAVE_MMAP
static unsigned int max_n_mmaps = 0;
static unsigned long max_mmapped_mem = 0;
#endif
/*
  Debugging support
*/
#ifdef DEBUG
/*
  These routines make a number of assertions about the states
  of data structures that should be true at all times. If any
  are not true, it's very likely that a user program has somehow
  trashed memory. (It's also possible that there is a coding error
  in malloc. In which case, please report it!)
*/
#if __STD_C
static void do_check_chunk(mchunkptr p)
#else
static void do_check_chunk(p) mchunkptr p;
#endif
{
  INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
  /* No checkable chunk is mmapped */
  assert(!chunk_is_mmapped(p));
  /* Check for legal address ... */
  assert((char*)p >= sbrk_base);
  if (p != top)
    assert((char*)p + sz <= (char*)top);
  else
    assert((char*)p + sz <= sbrk_base + sbrked_mem);
}
#if __STD_C
static void do_check_free_chunk(mchunkptr p)
#else
static void do_check_free_chunk(p) mchunkptr p;
#endif
{
  INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
  mchunkptr next = chunk_at_offset(p, sz);
  do_check_chunk(p);
  /* Check whether it claims to be free ... */
  assert(!inuse(p));
  /* Unless a special marker, must have OK fields */
  if ((long)sz >= (long)MINSIZE)
  {
    assert((sz & MALLOC_ALIGN_MASK) == 0);
    assert(aligned_OK(chunk2mem(p)));
    /* ... matching footer field */
    assert(next->prev_size == sz);
    /* ... and is fully consolidated */
    assert(prev_inuse(p));
    assert (next == top || inuse(next));
    /* ... and has minimally sane links */
    assert(p->fd->bk == p);
    assert(p->bk->fd == p);
  }
  else /* markers are always of size SIZE_SZ */
    assert(sz == SIZE_SZ);
}
#if __STD_C
static void do_check_inuse_chunk(mchunkptr p)
#else
static void do_check_inuse_chunk(p) mchunkptr p;
#endif
{
  mchunkptr next = next_chunk(p);
  do_check_chunk(p);
  /* Check whether it claims to be in use ... */
  assert(inuse(p));
  /* ... and is surrounded by OK chunks.
    Since more things can be checked with free chunks than inuse ones,
    if an inuse chunk borders them and debug is on, it's worth doing them.
  */
  if (!prev_inuse(p))
  {
    mchunkptr prv = prev_chunk(p);
    assert(next_chunk(prv) == p);
    do_check_free_chunk(prv);
  }
  if (next == top)
  {
    assert(prev_inuse(next));
    assert(chunksize(next) >= MINSIZE);
  }
  else if (!inuse(next))
    do_check_free_chunk(next);
}
#if __STD_C
static void do_check_malloced_chunk(mchunkptr p, INTERNAL_SIZE_T s)
#else
static void do_check_malloced_chunk(p, s) mchunkptr p; INTERNAL_SIZE_T s;
#endif
{
  INTERNAL_SIZE_T sz = p->size & ~PREV_INUSE;
  long room = sz - s;
  do_check_inuse_chunk(p);
  /* Legal size ... */
  assert((long)sz >= (long)MINSIZE);
  assert((sz & MALLOC_ALIGN_MASK) == 0);
  assert(room >= 0);
  assert(room < (long)MINSIZE);
  /* ... and alignment */
  assert(aligned_OK(chunk2mem(p)));
  /* ... and was allocated at front of an available chunk */
  assert(prev_inuse(p));
}
#define check_free_chunk(P)  do_check_free_chunk(P)
#define check_inuse_chunk(P) do_check_inuse_chunk(P)
#define check_chunk(P) do_check_chunk(P)
#define check_malloced_chunk(P,N) do_check_malloced_chunk(P,N)
#else
#define check_free_chunk(P)
#define check_inuse_chunk(P)
#define check_chunk(P)
#define check_malloced_chunk(P,N)
#endif
/*
  Macro-based internal utilities
*/
/*
  Linking chunks in bin lists.
  Call these only with variables, not arbitrary expressions, as arguments.
*/
/*
  Place chunk p of size s in its bin, in size order,
  putting it ahead of others of same size.
*/
#define frontlink(P, S, IDX, BK, FD)                                          \
{                                                                             \
  if (S < MAX_SMALLBIN_SIZE)                                                  \
  {                                                                           \
    IDX = smallbin_index(S);                                                  \
    mark_binblock(IDX);                                                       \
    BK = bin_at(IDX);                                                         \
    FD = BK->fd;                                                              \
    P->bk = BK;                                                               \
    P->fd = FD;                                                               \
    FD->bk = BK->fd = P;                                                      \
  }                                                                           \
  else                                                                        \
  {                                                                           \
    IDX = bin_index(S);                                                       \
    BK = bin_at(IDX);                                                         \
    FD = BK->fd;                                                              \
    if (FD == BK) mark_binblock(IDX);                                         \
    else                                                                      \
    {                                                                         \
      while (FD != BK && S < chunksize(FD)) FD = FD->fd;                      \
      BK = FD->bk;                                                            \
    }                                                                         \
    P->bk = BK;                                                               \
    P->fd = FD;                                                               \
    FD->bk = BK->fd = P;                                                      \
  }                                                                           \
}
/* take a chunk off a list */
#define unlink(P, BK, FD)                                                     \
{                                                                             \
  BK = P->bk;                                                                 \
  FD = P->fd;                                                                 \
  FD->bk = BK;                                                                \
  BK->fd = FD;                                                                \
}                                                                             \
/* Place p as the last remainder */
#define link_last_remainder(P)                                                \
{                                                                             \
  last_remainder->fd = last_remainder->bk =  P;                               \
  P->fd = P->bk = last_remainder;                                             \
}
/* Clear the last_remainder bin */
#define clear_last_remainder \
  (last_remainder->fd = last_remainder->bk = last_remainder)
/* Routines dealing with mmap(). */
#if HAVE_MMAP
#if __STD_C
static mchunkptr mmap_chunk(size_t size)
#else
static mchunkptr mmap_chunk(size) size_t size;
#endif
{
  size_t page_mask = malloc_getpagesize - 1;
  mchunkptr p;
#ifndef MAP_ANONYMOUS
  static int fd = -1;
#endif
  if(n_mmaps >= n_mmaps_max) return 0; /* too many regions */
  /* For mmapped chunks, the overhead is one SIZE_SZ unit larger, because
   * there is no following chunk whose prev_size field could be used.
   */
  size = (size + SIZE_SZ + page_mask) & ~page_mask;
#ifdef MAP_ANONYMOUS
  p = (mchunkptr)mmap(0, size, PROT_READ|PROT_WRITE,
              MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
#else /* !MAP_ANONYMOUS */
  if (fd < 0)
  {
    fd = open("/dev/zero", O_RDWR);
    if(fd < 0) return 0;
  }
  p = (mchunkptr)mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
#endif
  if(p == (mchunkptr)-1) return 0;
  n_mmaps++;
  if (n_mmaps > max_n_mmaps) max_n_mmaps = n_mmaps;
  /* We demand that eight bytes into a page must be 8-byte aligned. */
  assert(aligned_OK(chunk2mem(p)));
  /* The offset to the start of the mmapped region is stored
   * in the prev_size field of the chunk; normally it is zero,
   * but that can be changed in memalign().
   */
  p->prev_size = 0;
  set_head(p, size|IS_MMAPPED);
  mmapped_mem += size;
  if ((unsigned long)mmapped_mem > (unsigned long)max_mmapped_mem)
    max_mmapped_mem = mmapped_mem;
  if ((unsigned long)(mmapped_mem + sbrked_mem) > (unsigned long)max_total_mem)
    max_total_mem = mmapped_mem + sbrked_mem;
  return p;
}
#if __STD_C
static void munmap_chunk(mchunkptr p)
#else
static void munmap_chunk(p) mchunkptr p;
#endif
{
  INTERNAL_SIZE_T size = chunksize(p);
  int ret;
  assert (chunk_is_mmapped(p));
  assert(! ((char*)p >= sbrk_base && (char*)p < sbrk_base + sbrked_mem));
  assert((n_mmaps > 0));
  assert(((p->prev_size + size) & (malloc_getpagesize-1)) == 0);
  n_mmaps--;
  mmapped_mem -= (size + p->prev_size);
  ret = munmap((char *)p - p->prev_size, size + p->prev_size);
  /* munmap returns non-zero on failure */
  assert(ret == 0);
}
#if HAVE_MREMAP
#if __STD_C
static mchunkptr mremap_chunk(mchunkptr p, size_t new_size)
#else
static mchunkptr mremap_chunk(p, new_size) mchunkptr p; size_t new_size;
#endif
{
  size_t page_mask = malloc_getpagesize - 1;
  INTERNAL_SIZE_T offset = p->prev_size;
  INTERNAL_SIZE_T size = chunksize(p);
  char *cp;
  assert (chunk_is_mmapped(p));
  assert(! ((char*)p >= sbrk_base && (char*)p < sbrk_base + sbrked_mem));
  assert((n_mmaps > 0));
  assert(((size + offset) & (malloc_getpagesize-1)) == 0);
  /* Note the extra SIZE_SZ overhead as in mmap_chunk(). */
  new_size = (new_size + offset + SIZE_SZ + page_mask) & ~page_mask;
  cp = (char *)mremap((char *)p - offset, size + offset, new_size, 1);
  if (cp == (char *)-1) return 0;
  p = (mchunkptr)(cp + offset);
  assert(aligned_OK(chunk2mem(p)));
  assert((p->prev_size == offset));
  set_head(p, (new_size - offset)|IS_MMAPPED);
  mmapped_mem -= size + offset;
  mmapped_mem += new_size;
  if ((unsigned long)mmapped_mem > (unsigned long)max_mmapped_mem)
    max_mmapped_mem = mmapped_mem;
  if ((unsigned long)(mmapped_mem + sbrked_mem) > (unsigned long)max_total_mem)
    max_total_mem = mmapped_mem + sbrked_mem;
  return p;
}
#endif /* HAVE_MREMAP */
#endif /* HAVE_MMAP */
/*
  Extend the top-most chunk by obtaining memory from system.
  Main interface to sbrk (but see also malloc_trim).
*/
#if __STD_C
static void malloc_extend_top(INTERNAL_SIZE_T nb)
#else
static void malloc_extend_top(nb) INTERNAL_SIZE_T nb;
#endif
{
  char*     brk;                  /* return value from sbrk */
  INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of sbrked space */
  INTERNAL_SIZE_T correction;     /* bytes for 2nd sbrk call */
  char*     new_brk;              /* return of 2nd sbrk call */
  INTERNAL_SIZE_T top_size;       /* new size of top chunk */
  mchunkptr old_top     = top;  /* Record state of old top */
  INTERNAL_SIZE_T old_top_size = chunksize(old_top);
  char*     old_end      = (char*)(chunk_at_offset(old_top, old_top_size));
  /* Pad request with top_pad plus minimal overhead */
  INTERNAL_SIZE_T    sbrk_size     = nb + top_pad + MINSIZE;
  unsigned long pagesz    = malloc_getpagesize;
  /* If not the first time through, round to preserve page boundary */
  /* Otherwise, we need to correct to a page size below anyway. */
  /* (We also correct below if an intervening foreign sbrk call.) */
  if (sbrk_base != (char*)(-1))
    sbrk_size = (sbrk_size + (pagesz - 1)) & ~(pagesz - 1);
  brk = (char*)(MORECORE (sbrk_size));
  /* Fail if sbrk failed or if a foreign sbrk call killed our space */
  if (brk == (char*)(MORECORE_FAILURE) ||
      (brk < old_end && old_top != initial_top))
    return;
  sbrked_mem += sbrk_size;
  if (brk == old_end) /* can just add bytes to current top */
  {
    top_size = sbrk_size + old_top_size;
    set_head(top, top_size | PREV_INUSE);
  }
  else
  {
    if (sbrk_base == (char*)(-1))  /* First time through. Record base */
      sbrk_base = brk;
    else  /* Someone else called sbrk().  Count those bytes as sbrked_mem. */
      sbrked_mem += brk - (char*)old_end;
    /* Guarantee alignment of first new chunk made from this space */
    front_misalign = (unsigned long)chunk2mem(brk) & MALLOC_ALIGN_MASK;
    if (front_misalign > 0)
    {
      correction = (MALLOC_ALIGNMENT) - front_misalign;
      brk += correction;
    }
    else
      correction = 0;
    /* Guarantee the next brk will be at a page boundary */
    correction += ((((unsigned long)(brk + sbrk_size))+(pagesz-1)) &
           ~(pagesz - 1)) - ((unsigned long)(brk + sbrk_size));
    /* Allocate correction */
    new_brk = (char*)(MORECORE (correction));
    if (new_brk == (char*)(MORECORE_FAILURE)) return;
    sbrked_mem += correction;
    top = (mchunkptr)brk;
    top_size = new_brk - brk + correction;
    set_head(top, top_size | PREV_INUSE);
    if (old_top != initial_top)
    {
      /* There must have been an intervening foreign sbrk call. */
      /* A double fencepost is necessary to prevent consolidation */
      /* If not enough space to do this, then user did something very wrong */
      if (old_top_size < MINSIZE)
      {
    set_head(top, PREV_INUSE); /* will force null return from malloc */
    return;
      }
      /* Also keep size a multiple of MALLOC_ALIGNMENT */
      old_top_size = (old_top_size - 3*SIZE_SZ) & ~MALLOC_ALIGN_MASK;
      set_head_size(old_top, old_top_size);
      chunk_at_offset(old_top, old_top_size          )->size =
    SIZE_SZ|PREV_INUSE;
      chunk_at_offset(old_top, old_top_size + SIZE_SZ)->size =
    SIZE_SZ|PREV_INUSE;
      /* If possible, release the rest. */
      if (old_top_size >= MINSIZE)
    fREe(chunk2mem(old_top));
    }
  }
  if ((unsigned long)sbrked_mem > (unsigned long)max_sbrked_mem)
    max_sbrked_mem = sbrked_mem;
  if ((unsigned long)(mmapped_mem + sbrked_mem) > (unsigned long)max_total_mem)
    max_total_mem = mmapped_mem + sbrked_mem;
  /* We always land on a page boundary */
  assert(((unsigned long)((char*)top + top_size) & (pagesz - 1)) == 0);
}
/* Main public routines */
/*
  Malloc Algorthim:
    The requested size is first converted into a usable form, `nb'.
    This currently means to add 4 bytes overhead plus possibly more to
    obtain 8-byte alignment and/or to obtain a size of at least
    MINSIZE (currently 16 bytes), the smallest allocatable size.
    (All fits are considered `exact' if they are within MINSIZE bytes.)
    From there, the first successful of the following steps is taken:
      1. The bin corresponding to the request size is scanned, and if
     a chunk of exactly the right size is found, it is taken.
      2. The most recently remaindered chunk is used if it is big
     enough.  This is a form of (roving) first fit, used only in
     the absence of exact fits. Runs of consecutive requests use
     the remainder of the chunk used for the previous such request
     whenever possible. This limited use of a first-fit style
     allocation strategy tends to give contiguous chunks
     coextensive lifetimes, which improves locality and can reduce
     fragmentation in the long run.
      3. Other bins are scanned in increasing size order, using a
     chunk big enough to fulfill the request, and splitting off
     any remainder.  This search is strictly by best-fit; i.e.,
     the smallest (with ties going to approximately the least
     recently used) chunk that fits is selected.
      4. If large enough, the chunk bordering the end of memory
     (`top') is split off. (This use of `top' is in accord with
     the best-fit search rule.  In effect, `top' is treated as
     larger (and thus less well fitting) than any other available
     chunk since it can be extended to be as large as necessary
     (up to system limitations).
      5. If the request size meets the mmap threshold and the
     system supports mmap, and there are few enough currently
     allocated mmapped regions, and a call to mmap succeeds,
     the request is allocated via direct memory mapping.
      6. Otherwise, the top of memory is extended by
     obtaining more space from the system (normally using sbrk,
     but definable to anything else via the MORECORE macro).
     Memory is gathered from the system (in system page-sized
     units) in a way that allows chunks obtained across different
     sbrk calls to be consolidated, but does not require
     contiguous memory. Thus, it should be safe to intersperse
     mallocs with other sbrk calls.
      All allocations are made from the the `lowest' part of any found
      chunk. (The implementation invariant is that prev_inuse is
      always true of any allocated chunk; i.e., that each allocated
      chunk borders either a previously allocated and still in-use chunk,
      or the base of its memory arena.)
*/
#if __STD_C
Void_t* mALLOc(size_t bytes)
#else
Void_t* mALLOc(bytes) size_t bytes;
#endif
{
  mchunkptr victim;                  /* inspected/selected chunk */
  INTERNAL_SIZE_T victim_size;       /* its size */
  int       idx;                     /* index for bin traversal */
  mbinptr   bin;                     /* associated bin */
  mchunkptr remainder;               /* remainder from a split */
  long      remainder_size;          /* its size */
  int       remainder_index;         /* its bin index */
  unsigned long block;               /* block traverser bit */
  int       startidx;                /* first bin of a traversed block */
  mchunkptr fwd;                     /* misc temp for linking */
  mchunkptr bck;                     /* misc temp for linking */
  mbinptr q;                         /* misc temp */
  INTERNAL_SIZE_T nb;
  /* check if mem_malloc_init() was run */
  if ((mem_malloc_start == 0) && (mem_malloc_end == 0)) {
    /* not initialized yet */
    return NULL;
  }
  if ((long)bytes < 0) return NULL;
  nb = request2size(bytes);  /* padded request size; */
  /* Check for exact match in a bin */
  if (is_small_request(nb))  /* Faster version for small requests */
  {
    idx = smallbin_index(nb);
    /* No traversal or size check necessary for small bins.  */
    q = bin_at(idx);
    victim = last(q);
    /* Also scan the next one, since it would have a remainder < MINSIZE */
    if (victim == q)
    {
      q = next_bin(q);
      victim = last(q);
    }
    if (victim != q)
    {
      victim_size = chunksize(victim);
      unlink(victim, bck, fwd);
      set_inuse_bit_at_offset(victim, victim_size);
      check_malloced_chunk(victim, nb);
      return chunk2mem(victim);
    }
    idx += 2; /* Set for bin scan below. We've already scanned 2 bins. */
  }
  else
  {
    idx = bin_index(nb);
    bin = bin_at(idx);
    for (victim = last(bin); victim != bin; victim = victim->bk)
    {
      victim_size = chunksize(victim);
      remainder_size = victim_size - nb;
      if (remainder_size >= (long)MINSIZE) /* too big */
      {
    --idx; /* adjust to rescan below after checking last remainder */
    break;
      }
      else if (remainder_size >= 0) /* exact fit */
      {
    unlink(victim, bck, fwd);
    set_inuse_bit_at_offset(victim, victim_size);
    check_malloced_chunk(victim, nb);
    return chunk2mem(victim);
      }
    }
    ++idx;
  }
  /* Try to use the last split-off remainder */
  if ( (victim = last_remainder->fd) != last_remainder)
  {
    victim_size = chunksize(victim);
    remainder_size = victim_size - nb;
    if (remainder_size >= (long)MINSIZE) /* re-split */
    {
      remainder = chunk_at_offset(victim, nb);
      set_head(victim, nb | PREV_INUSE);
      link_last_remainder(remainder);
      set_head(remainder, remainder_size | PREV_INUSE);
      set_foot(remainder, remainder_size);
      check_malloced_chunk(victim, nb);
      return chunk2mem(victim);
    }
    clear_last_remainder;
    if (remainder_size >= 0)  /* exhaust */
    {
      set_inuse_bit_at_offset(victim, victim_size);
      check_malloced_chunk(victim, nb);
      return chunk2mem(victim);
    }
    /* Else place in bin */
    frontlink(victim, victim_size, remainder_index, bck, fwd);
  }
  /*
     If there are any possibly nonempty big-enough blocks,
     search for best fitting chunk by scanning bins in blockwidth units.
  */
  if ( (block = idx2binblock(idx)) <= binblocks_r)
  {
    /* Get to the first marked block */
    if ( (block & binblocks_r) == 0)
    {
      /* force to an even block boundary */
      idx = (idx & ~(BINBLOCKWIDTH - 1)) + BINBLOCKWIDTH;
      block <<= 1;
      while ((block & binblocks_r) == 0)
      {
    idx += BINBLOCKWIDTH;
    block <<= 1;
      }
    }
    /* For each possibly nonempty block ... */
    for (;;)
    {
      startidx = idx;          /* (track incomplete blocks) */
      q = bin = bin_at(idx);
      /* For each bin in this block ... */
      do
      {
    /* Find and use first big enough chunk ... */
    for (victim = last(bin); victim != bin; victim = victim->bk)
    {
      victim_size = chunksize(victim);
      remainder_size = victim_size - nb;
      if (remainder_size >= (long)MINSIZE) /* split */
      {
        remainder = chunk_at_offset(victim, nb);
        set_head(victim, nb | PREV_INUSE);
        unlink(victim, bck, fwd);
        link_last_remainder(remainder);
        set_head(remainder, remainder_size | PREV_INUSE);
        set_foot(remainder, remainder_size);
        check_malloced_chunk(victim, nb);
        return chunk2mem(victim);
      }
      else if (remainder_size >= 0)  /* take */
      {
        set_inuse_bit_at_offset(victim, victim_size);
        unlink(victim, bck, fwd);
        check_malloced_chunk(victim, nb);
        return chunk2mem(victim);
      }
    }
       bin = next_bin(bin);
      } while ((++idx & (BINBLOCKWIDTH - 1)) != 0);
      /* Clear out the block bit. */
      do   /* Possibly backtrack to try to clear a partial block */
      {
    if ((startidx & (BINBLOCKWIDTH - 1)) == 0)
    {
      av_[1] = (mbinptr)(binblocks_r & ~block);
      break;
    }
    --startidx;
       q = prev_bin(q);
      } while (first(q) == q);
      /* Get to the next possibly nonempty block */
      if ( (block <<= 1) <= binblocks_r && (block != 0) )
      {
    while ((block & binblocks_r) == 0)
    {
      idx += BINBLOCKWIDTH;
      block <<= 1;
    }
      }
      else
    break;
    }
  }
  /* Try to use top chunk */
  /* Require that there be a remainder, ensuring top always exists  */
  if ( (remainder_size = chunksize(top) - nb) < (long)MINSIZE)
  {
#if HAVE_MMAP
    /* If big and would otherwise need to extend, try to use mmap instead */
    if ((unsigned long)nb >= (unsigned long)mmap_threshold &&
    (victim = mmap_chunk(nb)) != 0)
      return chunk2mem(victim);
#endif
    /* Try to extend */
    malloc_extend_top(nb);
    if ( (remainder_size = chunksize(top) - nb) < (long)MINSIZE)
      return NULL; /* propagate failure */
  }
  victim = top;
  set_head(victim, nb | PREV_INUSE);
  top = chunk_at_offset(victim, nb);
  set_head(top, remainder_size | PREV_INUSE);
  check_malloced_chunk(victim, nb);
  return chunk2mem(victim);
}
/*
  free() algorithm :
    cases:
       1. free(0) has no effect.
       2. If the chunk was allocated via mmap, it is release via munmap().
       3. If a returned chunk borders the current high end of memory,
      it is consolidated into the top, and if the total unused
      topmost memory exceeds the trim threshold, malloc_trim is
      called.
       4. Other chunks are consolidated as they arrive, and
      placed in corresponding bins. (This includes the case of
      consolidating with the current `last_remainder').
*/
#if __STD_C
void fREe(Void_t* mem)
#else
void fREe(mem) Void_t* mem;
#endif
{
  mchunkptr p;         /* chunk corresponding to mem */
  INTERNAL_SIZE_T hd;  /* its head field */
  INTERNAL_SIZE_T sz;  /* its size */
  int       idx;       /* its bin index */
  mchunkptr next;      /* next contiguous chunk */
  INTERNAL_SIZE_T nextsz; /* its size */
  INTERNAL_SIZE_T prevsz; /* size of previous contiguous chunk */
  mchunkptr bck;       /* misc temp for linking */
  mchunkptr fwd;       /* misc temp for linking */
  int       islr;      /* track whether merging with last_remainder */
  if (mem == NULL)                              /* free(0) has no effect */
    return;
  p = mem2chunk(mem);
  hd = p->size;
#if HAVE_MMAP
  if (hd & IS_MMAPPED)                       /* release mmapped memory. */
  {
    munmap_chunk(p);
    return;
  }
#endif
  check_inuse_chunk(p);
  sz = hd & ~PREV_INUSE;
  next = chunk_at_offset(p, sz);
  nextsz = chunksize(next);
  if (next == top)                            /* merge with top */
  {
    sz += nextsz;
    if (!(hd & PREV_INUSE))                    /* consolidate backward */
    {
      prevsz = p->prev_size;
      p = chunk_at_offset(p, -((long) prevsz));
      sz += prevsz;
      unlink(p, bck, fwd);
    }
    set_head(p, sz | PREV_INUSE);
    top = p;
    if ((unsigned long)(sz) >= (unsigned long)trim_threshold)
      malloc_trim(top_pad);
    return;
  }
  set_head(next, nextsz);                    /* clear inuse bit */
  islr = 0;
  if (!(hd & PREV_INUSE))                    /* consolidate backward */
  {
    prevsz = p->prev_size;
    p = chunk_at_offset(p, -((long) prevsz));
    sz += prevsz;
    if (p->fd == last_remainder)             /* keep as last_remainder */
      islr = 1;
    else
      unlink(p, bck, fwd);
  }
  if (!(inuse_bit_at_offset(next, nextsz)))   /* consolidate forward */
  {
    sz += nextsz;
    if (!islr && next->fd == last_remainder)  /* re-insert last_remainder */
    {
      islr = 1;
      link_last_remainder(p);
    }
    else
      unlink(next, bck, fwd);
  }
  set_head(p, sz | PREV_INUSE);
  set_foot(p, sz);
  if (!islr)
    frontlink(p, sz, idx, bck, fwd);
}
/*
  Realloc algorithm:
    Chunks that were obtained via mmap cannot be extended or shrunk
    unless HAVE_MREMAP is defined, in which case mremap is used.
    Otherwise, if their reallocation is for additional space, they are
    copied.  If for less, they are just left alone.
    Otherwise, if the reallocation is for additional space, and the
    chunk can be extended, it is, else a malloc-copy-free sequence is
    taken.  There are several different ways that a chunk could be
    extended. All are tried:
       * Extending forward into following adjacent free chunk.
       * Shifting backwards, joining preceding adjacent space
       * Both shifting backwards and extending forward.
       * Extending into newly sbrked space
    Unless the #define REALLOC_ZERO_BYTES_FREES is set, realloc with a
    size argument of zero (re)allocates a minimum-sized chunk.
    If the reallocation is for less space, and the new request is for
    a `small' (<512 bytes) size, then the newly unused space is lopped
    off and freed.
    The old unix realloc convention of allowing the last-free'd chunk
    to be used as an argument to realloc is no longer supported.
    I don't know of any programs still relying on this feature,
    and allowing it would also allow too many other incorrect
    usages of realloc to be sensible.
*/
#if __STD_C
Void_t* rEALLOc(Void_t* oldmem, size_t bytes)
#else
Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes;
#endif
{
  INTERNAL_SIZE_T    nb;      /* padded request size */
  mchunkptr oldp;             /* chunk corresponding to oldmem */
  INTERNAL_SIZE_T    oldsize; /* its size */
  mchunkptr newp;             /* chunk to return */
  INTERNAL_SIZE_T    newsize; /* its size */
  Void_t*   newmem;           /* corresponding user mem */
  mchunkptr next;             /* next contiguous chunk after oldp */
  INTERNAL_SIZE_T  nextsize;  /* its size */
  mchunkptr prev;             /* previous contiguous chunk before oldp */
  INTERNAL_SIZE_T  prevsize;  /* its size */
  mchunkptr remainder;        /* holds split off extra space from newp */
  INTERNAL_SIZE_T  remainder_size;   /* its size */
  mchunkptr bck;              /* misc temp for linking */
  mchunkptr fwd;              /* misc temp for linking */
#ifdef REALLOC_ZERO_BYTES_FREES
  if (bytes == 0) { fREe(oldmem); return 0; }
#endif
  if ((long)bytes < 0) return NULL;
  /* realloc of null is supposed to be same as malloc */
  if (oldmem == NULL) return mALLOc(bytes);
  newp    = oldp    = mem2chunk(oldmem);
  newsize = oldsize = chunksize(oldp);
  nb = request2size(bytes);
#if HAVE_MMAP
  if (chunk_is_mmapped(oldp))
  {
#if HAVE_MREMAP
    newp = mremap_chunk(oldp, nb);
    if(newp) return chunk2mem(newp);
#endif
    /* Note the extra SIZE_SZ overhead. */
    if(oldsize - SIZE_SZ >= nb) return oldmem; /* do nothing */
    /* Must alloc, copy, free. */
    newmem = mALLOc(bytes);
    if (newmem == 0) return 0; /* propagate failure */
    MALLOC_COPY(newmem, oldmem, oldsize - 2*SIZE_SZ);
    munmap_chunk(oldp);
    return newmem;
  }
#endif
  check_inuse_chunk(oldp);
  if ((long)(oldsize) < (long)(nb))
  {
    /* Try expanding forward */
    next = chunk_at_offset(oldp, oldsize);
    if (next == top || !inuse(next))
    {
      nextsize = chunksize(next);
      /* Forward into top only if a remainder */
      if (next == top)
      {
    if ((long)(nextsize + newsize) >= (long)(nb + MINSIZE))
    {
      newsize += nextsize;
      top = chunk_at_offset(oldp, nb);
      set_head(top, (newsize - nb) | PREV_INUSE);
      set_head_size(oldp, nb);
      return chunk2mem(oldp);
    }
      }
      /* Forward into next chunk */
      else if (((long)(nextsize + newsize) >= (long)(nb)))
      {
    unlink(next, bck, fwd);
    newsize  += nextsize;
    goto split;
      }
    }
    else
    {
      next = NULL;
      nextsize = 0;
    }
    /* Try shifting backwards. */
    if (!prev_inuse(oldp))
    {
      prev = prev_chunk(oldp);
      prevsize = chunksize(prev);
      /* try forward + backward first to save a later consolidation */
      if (next != NULL)
      {
    /* into top */
    if (next == top)
    {
      if ((long)(nextsize + prevsize + newsize) >= (long)(nb + MINSIZE))
      {
        unlink(prev, bck, fwd);
        newp = prev;
        newsize += prevsize + nextsize;
        newmem = chunk2mem(newp);
        MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
        top = chunk_at_offset(newp, nb);
        set_head(top, (newsize - nb) | PREV_INUSE);
        set_head_size(newp, nb);
        return newmem;
      }
    }
    /* into next chunk */
    else if (((long)(nextsize + prevsize + newsize) >= (long)(nb)))
    {
      unlink(next, bck, fwd);
      unlink(prev, bck, fwd);
      newp = prev;
      newsize += nextsize + prevsize;
      newmem = chunk2mem(newp);
      MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
      goto split;
    }
      }
      /* backward only */
      if (prev != NULL && (long)(prevsize + newsize) >= (long)nb)
      {
    unlink(prev, bck, fwd);
    newp = prev;
    newsize += prevsize;
    newmem = chunk2mem(newp);
    MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
    goto split;
      }
    }
    /* Must allocate */
    newmem = mALLOc (bytes);
    if (newmem == NULL)  /* propagate failure */
      return NULL;
    /* Avoid copy if newp is next chunk after oldp. */
    /* (This can only happen when new chunk is sbrk'ed.) */
    if ( (newp = mem2chunk(newmem)) == next_chunk(oldp))
    {
      newsize += chunksize(newp);
      newp = oldp;
      goto split;
    }
    /* Otherwise copy, free, and exit */
    MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ);
    fREe(oldmem);
    return newmem;
  }
 split:  /* split off extra room in old or expanded chunk */
  if (newsize - nb >= MINSIZE) /* split off remainder */
  {
    remainder = chunk_at_offset(newp, nb);
    remainder_size = newsize - nb;
    set_head_size(newp, nb);
    set_head(remainder, remainder_size | PREV_INUSE);
    set_inuse_bit_at_offset(remainder, remainder_size);
    fREe(chunk2mem(remainder)); /* let free() deal with it */
  }
  else
  {
    set_head_size(newp, newsize);
    set_inuse_bit_at_offset(newp, newsize);
  }
  check_inuse_chunk(newp);
  return chunk2mem(newp);
}
/*
  memalign algorithm:
    memalign requests more than enough space from malloc, finds a spot
    within that chunk that meets the alignment request, and then
    possibly frees the leading and trailing space.
    The alignment argument must be a power of two. This property is not
    checked by memalign, so misuse may result in random runtime errors.
    8-byte alignment is guaranteed by normal malloc calls, so don't
    bother calling memalign with an argument of 8 or less.
    Overreliance on memalign is a sure way to fragment space.
*/
#if __STD_C
Void_t* mEMALIGn(size_t alignment, size_t bytes)
#else
Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes;
#endif
{
  INTERNAL_SIZE_T    nb;      /* padded  request size */
  char*     m;                /* memory returned by malloc call */
  mchunkptr p;                /* corresponding chunk */
  char*     brk;              /* alignment point within p */
  mchunkptr newp;             /* chunk to return */
  INTERNAL_SIZE_T  newsize;   /* its size */
  INTERNAL_SIZE_T  leadsize;  /* leading space befor alignment point */
  mchunkptr remainder;        /* spare room at end to split off */
  long      remainder_size;   /* its size */
  if ((long)bytes < 0) return NULL;
  /* If need less alignment than we give anyway, just relay to malloc */
  if (alignment <= MALLOC_ALIGNMENT) return mALLOc(bytes);
  /* Otherwise, ensure that it is at least a minimum chunk size */
  if (alignment <  MINSIZE) alignment = MINSIZE;
  /* Call malloc with worst case padding to hit alignment. */
  nb = request2size(bytes);
  m  = (char*)(mALLOc(nb + alignment + MINSIZE));
  if (m == NULL) return NULL; /* propagate failure */
  p = mem2chunk(m);
  if ((((unsigned long)(m)) % alignment) == 0) /* aligned */
  {
#if HAVE_MMAP
    if(chunk_is_mmapped(p))
      return chunk2mem(p); /* nothing more to do */
#endif
  }
  else /* misaligned */
  {
    /*
      Find an aligned spot inside chunk.
      Since we need to give back leading space in a chunk of at
      least MINSIZE, if the first calculation places us at
      a spot with less than MINSIZE leader, we can move to the
      next aligned spot -- we've allocated enough total room so that
      this is always possible.
    */
    brk = (char*)mem2chunk(((unsigned long)(m + alignment - 1)) & -((signed) alignment));
    if ((long)(brk - (char*)(p)) < MINSIZE) brk = brk + alignment;
    newp = (mchunkptr)brk;
    leadsize = brk - (char*)(p);
    newsize = chunksize(p) - leadsize;
#if HAVE_MMAP
    if(chunk_is_mmapped(p))
    {
      newp->prev_size = p->prev_size + leadsize;
      set_head(newp, newsize|IS_MMAPPED);
      return chunk2mem(newp);
    }
#endif
    /* give back leader, use the rest */
    set_head(newp, newsize | PREV_INUSE);
    set_inuse_bit_at_offset(newp, newsize);
    set_head_size(p, leadsize);
    fREe(chunk2mem(p));
    p = newp;
    assert (newsize >= nb && (((unsigned long)(chunk2mem(p))) % alignment) == 0);
  }
  /* Also give back spare room at the end */
  remainder_size = chunksize(p) - nb;
  if (remainder_size >= (long)MINSIZE)
  {
    remainder = chunk_at_offset(p, nb);
    set_head(remainder, remainder_size | PREV_INUSE);
    set_head_size(p, nb);
    fREe(chunk2mem(remainder));
  }
  check_inuse_chunk(p);
  return chunk2mem(p);
}
/*
    valloc just invokes memalign with alignment argument equal
    to the page size of the system (or as near to this as can
    be figured out from all the includes/defines above.)
*/
#if __STD_C
Void_t* vALLOc(size_t bytes)
#else
Void_t* vALLOc(bytes) size_t bytes;
#endif
{
  return mEMALIGn (malloc_getpagesize, bytes);
}
/*
  pvalloc just invokes valloc for the nearest pagesize
  that will accommodate request
*/
#if __STD_C
Void_t* pvALLOc(size_t bytes)
#else
Void_t* pvALLOc(bytes) size_t bytes;
#endif
{
  size_t pagesize = malloc_getpagesize;
  return mEMALIGn (pagesize, (bytes + pagesize - 1) & ~(pagesize - 1));
}
/*
  calloc calls malloc, then zeroes out the allocated chunk.
*/
#if __STD_C
Void_t* cALLOc(size_t n, size_t elem_size)
#else
Void_t* cALLOc(n, elem_size) size_t n; size_t elem_size;
#endif
{
  mchunkptr p;
  INTERNAL_SIZE_T csz;
  INTERNAL_SIZE_T sz = n * elem_size;
  /* check if expand_top called, in which case don't need to clear */
#if MORECORE_CLEARS
  mchunkptr oldtop = top;
  INTERNAL_SIZE_T oldtopsize = chunksize(top);
#endif
  Void_t* mem = mALLOc (sz);
  if ((long)n < 0) return NULL;
  if (mem == NULL)
    return NULL;
  else
  {
    p = mem2chunk(mem);
    /* Two optional cases in which clearing not necessary */
#if HAVE_MMAP
    if (chunk_is_mmapped(p)) return mem;
#endif
    csz = chunksize(p);
#if MORECORE_CLEARS
    if (p == oldtop && csz > oldtopsize)
    {
      /* clear only the bytes from non-freshly-sbrked memory */
      csz = oldtopsize;
    }
#endif
    MALLOC_ZERO(mem, csz - SIZE_SZ);
    return mem;
  }
}
/*
  cfree just calls free. It is needed/defined on some systems
  that pair it with calloc, presumably for odd historical reasons.
*/
#if !defined(INTERNAL_LINUX_C_LIB) || !defined(__ELF__)
#if __STD_C
void cfree(Void_t *mem)
#else
void cfree(mem) Void_t *mem;
#endif
{
  fREe(mem);
}
#endif
/*
    Malloc_trim gives memory back to the system (via negative
    arguments to sbrk) if there is unused memory at the `high' end of
    the malloc pool. You can call this after freeing large blocks of
    memory to potentially reduce the system-level memory requirements
    of a program. However, it cannot guarantee to reduce memory. Under
    some allocation patterns, some large free blocks of memory will be
    locked between two used chunks, so they cannot be given back to
    the system.
    The `pad' argument to malloc_trim represents the amount of free
    trailing space to leave untrimmed. If this argument is zero,
    only the minimum amount of memory to maintain internal data
    structures will be left (one page or less). Non-zero arguments
    can be supplied to maintain enough trailing space to service
    future expected allocations without having to re-obtain memory
    from the system.
    Malloc_trim returns 1 if it actually released any memory, else 0.
*/
#if __STD_C
int malloc_trim(size_t pad)
#else
int malloc_trim(pad) size_t pad;
#endif
{
  long  top_size;        /* Amount of top-most memory */
  long  extra;           /* Amount to release */
  char* current_brk;     /* address returned by pre-check sbrk call */
  char* new_brk;         /* address returned by negative sbrk call */
  unsigned long pagesz = malloc_getpagesize;
  top_size = chunksize(top);
  extra = ((top_size - pad - MINSIZE + (pagesz-1)) / pagesz - 1) * pagesz;
  if (extra < (long)pagesz)  /* Not enough memory to release */
    return 0;
  else
  {
    /* Test to make sure no one else called sbrk */
    current_brk = (char*)(MORECORE (0));
    if (current_brk != (char*)(top) + top_size)
      return 0;     /* Apparently we don't own memory; must fail */
    else
    {
      new_brk = (char*)(MORECORE (-extra));
      if (new_brk == (char*)(MORECORE_FAILURE)) /* sbrk failed? */
      {
    /* Try to figure out what we have */
    current_brk = (char*)(MORECORE (0));
    top_size = current_brk - (char*)top;
    if (top_size >= (long)MINSIZE) /* if not, we are very very dead! */
    {
      sbrked_mem = current_brk - sbrk_base;
      set_head(top, top_size | PREV_INUSE);
    }
    check_chunk(top);
    return 0;
      }
      else
      {
    /* Success. Adjust top accordingly. */
    set_head(top, (top_size - extra) | PREV_INUSE);
    sbrked_mem -= extra;
    check_chunk(top);
    return 1;
      }
    }
  }
}
/*
  malloc_usable_size:
    This routine tells you how many bytes you can actually use in an
    allocated chunk, which may be more than you requested (although
    often not). You can use this many bytes without worrying about
    overwriting other allocated objects. Not a particularly great
    programming practice, but still sometimes useful.
*/
#if __STD_C
size_t malloc_usable_size(Void_t* mem)
#else
size_t malloc_usable_size(mem) Void_t* mem;
#endif
{
  mchunkptr p;
  if (mem == NULL)
    return 0;
  else
  {
    p = mem2chunk(mem);
    if(!chunk_is_mmapped(p))
    {
      if (!inuse(p)) return 0;
      check_inuse_chunk(p);
      return chunksize(p) - SIZE_SZ;
    }
    return chunksize(p) - 2*SIZE_SZ;
  }
}
/* Utility to update current_mallinfo for malloc_stats and mallinfo() */
#ifdef DEBUG
static void malloc_update_mallinfo()
{
  int i;
  mbinptr b;
  mchunkptr p;
#ifdef DEBUG
  mchunkptr q;
#endif
  INTERNAL_SIZE_T avail = chunksize(top);
  int   navail = ((long)(avail) >= (long)MINSIZE)? 1 : 0;
  for (i = 1; i < NAV; ++i)
  {
    b = bin_at(i);
    for (p = last(b); p != b; p = p->bk)
    {
#ifdef DEBUG
      check_free_chunk(p);
      for (q = next_chunk(p);
       q < top && inuse(q) && (long)(chunksize(q)) >= (long)MINSIZE;
       q = next_chunk(q))
    check_inuse_chunk(q);
#endif
      avail += chunksize(p);
      navail++;
    }
  }
  current_mallinfo.ordblks = navail;
  current_mallinfo.uordblks = sbrked_mem - avail;
  current_mallinfo.fordblks = avail;
  current_mallinfo.hblks = n_mmaps;
  current_mallinfo.hblkhd = mmapped_mem;
  current_mallinfo.keepcost = chunksize(top);
}
#endif    /* DEBUG */
/*
  malloc_stats:
    Prints on the amount of space obtain from the system (both
    via sbrk and mmap), the maximum amount (which may be more than
    current if malloc_trim and/or munmap got called), the maximum
    number of simultaneous mmap regions used, and the current number
    of bytes allocated via malloc (or realloc, etc) but not yet
    freed. (Note that this is the number of bytes allocated, not the
    number requested. It will be larger than the number requested
    because of alignment and bookkeeping overhead.)
*/
#ifdef DEBUG
void malloc_stats()
{
  malloc_update_mallinfo();
  printf("max system bytes = %10u\n",
      (unsigned int)(max_total_mem));
  printf("system bytes     = %10u\n",
      (unsigned int)(sbrked_mem + mmapped_mem));
  printf("in use bytes     = %10u\n",
      (unsigned int)(current_mallinfo.uordblks + mmapped_mem));
#if HAVE_MMAP
  printf("max mmap regions = %10u\n",
      (unsigned int)max_n_mmaps);
#endif
}
#endif    /* DEBUG */
/*
  mallinfo returns a copy of updated current mallinfo.
*/
#ifdef DEBUG
struct mallinfo mALLINFo()
{
  malloc_update_mallinfo();
  return current_mallinfo;
}
#endif    /* DEBUG */
/*
  mallopt:
    mallopt is the general SVID/XPG interface to tunable parameters.
    The format is to provide a (parameter-number, parameter-value) pair.
    mallopt then sets the corresponding parameter to the argument
    value if it can (i.e., so long as the value is meaningful),
    and returns 1 if successful else 0.
    See descriptions of tunable parameters above.
*/
#if __STD_C
int mALLOPt(int param_number, int value)
#else
int mALLOPt(param_number, value) int param_number; int value;
#endif
{
  switch(param_number)
  {
    case M_TRIM_THRESHOLD:
      trim_threshold = value; return 1;
    case M_TOP_PAD:
      top_pad = value; return 1;
    case M_MMAP_THRESHOLD:
      mmap_threshold = value; return 1;
    case M_MMAP_MAX:
#if HAVE_MMAP
      n_mmaps_max = value; return 1;
#else
      if (value != 0) return 0; else  n_mmaps_max = value; return 1;
#endif
    default:
      return 0;
  }
}
/*
History:
    V2.6.6 Sun Dec  5 07:42:19 1999  Doug Lea  (dl at gee)
      * return null for negative arguments
      * Added Several WIN32 cleanups from Martin C. Fong <mcfong@yahoo.com>
     * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h'
      (e.g. WIN32 platforms)
     * Cleanup up header file inclusion for WIN32 platforms
     * Cleanup code to avoid Microsoft Visual C++ compiler complaints
     * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing
       memory allocation routines
     * Set 'malloc_getpagesize' for WIN32 platforms (needs more work)
     * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to
       usage of 'assert' in non-WIN32 code
     * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to
       avoid infinite loop
      * Always call 'fREe()' rather than 'free()'
    V2.6.5 Wed Jun 17 15:57:31 1998  Doug Lea  (dl at gee)
      * Fixed ordering problem with boundary-stamping
    V2.6.3 Sun May 19 08:17:58 1996  Doug Lea  (dl at gee)
      * Added pvalloc, as recommended by H.J. Liu
      * Added 64bit pointer support mainly from Wolfram Gloger
      * Added anonymously donated WIN32 sbrk emulation
      * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen
      * malloc_extend_top: fix mask error that caused wastage after
    foreign sbrks
      * Add linux mremap support code from HJ Liu
    V2.6.2 Tue Dec  5 06:52:55 1995  Doug Lea  (dl at gee)
      * Integrated most documentation with the code.
      * Add support for mmap, with help from
    Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
      * Use last_remainder in more cases.
      * Pack bins using idea from  colin@nyx10.cs.du.edu
      * Use ordered bins instead of best-fit threshhold
      * Eliminate block-local decls to simplify tracing and debugging.
      * Support another case of realloc via move into top
      * Fix error occuring when initial sbrk_base not word-aligned.
      * Rely on page size for units instead of SBRK_UNIT to
    avoid surprises about sbrk alignment conventions.
      * Add mallinfo, mallopt. Thanks to Raymond Nijssen
    (raymond@es.ele.tue.nl) for the suggestion.
      * Add `pad' argument to malloc_trim and top_pad mallopt parameter.
      * More precautions for cases where other routines call sbrk,
    courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de).
      * Added macros etc., allowing use in linux libc from
    H.J. Lu (hjl@gnu.ai.mit.edu)
      * Inverted this history list
    V2.6.1 Sat Dec  2 14:10:57 1995  Doug Lea  (dl at gee)
      * Re-tuned and fixed to behave more nicely with V2.6.0 changes.
      * Removed all preallocation code since under current scheme
    the work required to undo bad preallocations exceeds
    the work saved in good cases for most test programs.
      * No longer use return list or unconsolidated bins since
    no scheme using them consistently outperforms those that don't
    given above changes.
      * Use best fit for very large chunks to prevent some worst-cases.
      * Added some support for debugging
    V2.6.0 Sat Nov  4 07:05:23 1995  Doug Lea  (dl at gee)
      * Removed footers when chunks are in use. Thanks to
    Paul Wilson (wilson@cs.texas.edu) for the suggestion.
    V2.5.4 Wed Nov  1 07:54:51 1995  Doug Lea  (dl at gee)
      * Added malloc_trim, with help from Wolfram Gloger
    (wmglo@Dent.MED.Uni-Muenchen.DE).
    V2.5.3 Tue Apr 26 10:16:01 1994  Doug Lea  (dl at g)
    V2.5.2 Tue Apr  5 16:20:40 1994  Doug Lea  (dl at g)
      * realloc: try to expand in both directions
      * malloc: swap order of clean-bin strategy;
      * realloc: only conditionally expand backwards
      * Try not to scavenge used bins
      * Use bin counts as a guide to preallocation
      * Occasionally bin return list chunks in first scan
      * Add a few optimizations from colin@nyx10.cs.du.edu
    V2.5.1 Sat Aug 14 15:40:43 1993  Doug Lea  (dl at g)
      * faster bin computation & slightly different binning
      * merged all consolidations to one part of malloc proper
     (eliminating old malloc_find_space & malloc_clean_bin)
      * Scan 2 returns chunks (not just 1)
      * Propagate failure in realloc if malloc returns 0
      * Add stuff to allow compilation on non-ANSI compilers
      from kpv@research.att.com
    V2.5 Sat Aug  7 07:41:59 1993  Doug Lea  (dl at g.oswego.edu)
      * removed potential for odd address access in prev_chunk
      * removed dependency on getpagesize.h
      * misc cosmetics and a bit more internal documentation
      * anticosmetics: mangled names in macros to evade debugger strangeness
      * tested on sparc, hp-700, dec-mips, rs6000
      with gcc & native cc (hp, dec only) allowing
      Detlefs & Zorn comparison study (in SIGPLAN Notices.)
    Trial version Fri Aug 28 13:14:29 1992  Doug Lea  (dl at g.oswego.edu)
      * Based loosely on libg++-1.2X malloc. (It retains some of the overall
     structure of old version,  but most details differ.)
*/
linux-bsp/asm-study/yaffs2/common/makefile
New file
@@ -0,0 +1,97 @@
#*********************************************************************************
#      Copyright:  (C) 2012 CoherentPlus Sdn. Bhd.
#                  All rights reserved.
#
#       Filename:  Makefile
#    Description:  This is the common subdir Makefile which to compile all the C
#                  source code to object files and then generate the shared or
#                  static library named lib$(FOLDER_NAME).a orlib $(FOLDER_NAME).so,
#                  which depends on the variable $LINK_MODE.
#
#        Version:  1.0.0(10/08/2011~)
#                  Author:  Guo Wenxue <guowenxue@gmail.com>
#      ChangeLog:  1, Release initial version on "10/08/2011 01:29:33 AM"
#
#********************************************************************************/
PWD=$(shell pwd)
LOCAL_COMPILE=YES
LINK_MODE=STATIC
#If wanna compile in the subdir, not called by top makefile, uncomment it
ifneq (${TOP_COMPILE}, YES)
LOCAL_COMPILE=YES
endif
LIBNAME=$(shell basename ${PWD})
STALIB=lib${LIBNAME}.a
DYNLIB=lib${LIBNAME}.so
VPATH= .
SRCS = $(wildcard ${VPATH}/*.c)
OBJS = $(patsubst %.c,%.o,$(SRCS))
#======================================================
#  ---> Doesn't call by top makefile, compile by local
#======================================================
ifeq (${LOCAL_COMPILE}, YES)
ARCH?=arm920t
#ARCH?=i386
CFLAGS+=-fPIC
TMP=$(shell echo $(ARCH) | tr "[A-Z]" "[a-z]")
ifneq (,$(filter i386,$(TMP)))
    CROSS_COMPILE=
else
    CROSS_COMPILE=/opt/xtools/arm920t/bin/arm-linux-
endif
PRJDIR?=$(shell pwd)
CFLAGS+=-I${PRJDIR}
CC = ${CROSS_COMPILE}gcc
AR = ${CROSS_COMPILE}ar
endif #End local compile
ifeq ("${LINK_MODE}", "STATIC")
    LIBS = ${STALIB}
else
    LIBS=${DYNLIB}
endif
all: entry ${LIBS} install
entry:
    @echo " ";
    @echo " =========================================================";
    @echo " **     Compile subdir ${LIBNAME} for ${ARCH}             ";
    @echo " =========================================================";
#$(LD) -g --relocatable $(OBJS) -o lib${LIBNAME}.o
${STALIB}:    $(OBJS)
    $(AR) -rcu $@ $(OBJS)
${DYNLIB}:   $(OBJS)
    $(CC) -fPIC -shared -o $@ $(OBJS)
%.o : %.c
    $(CC) -c $< $(CFLAGS)
tag:
    @ctags --c-kinds=+defglmnstuvx --langmap=c:.c.h.ho.hem.het.hec.hev.him.hit.hic.hiv -R .
    @cscope -Rbq
install:
    @if [ ! -z "${LIBS_PATH}" ] ; then \
        mkdir -p ${LIBS_PATH} ; \
        cp ${LIBS} ${LIBS_PATH}; \
    fi;
clean:
    @rm -f *.o
    @rm -rf *.gdb *.a *.so
distclean: clean
    @rm -f  tags cscope*
.PHONY: clean entry
linux-bsp/asm-study/yaffs2/common/malloc.h
New file
@@ -0,0 +1,947 @@
/*
  A version of malloc/free/realloc written by Doug Lea and released to the
  public domain.  Send questions/comments/complaints/performance data
  to dl@cs.oswego.edu
* VERSION 2.6.6  Sun Mar  5 19:10:03 2000  Doug Lea  (dl at gee)
   Note: There may be an updated version of this malloc obtainable at
       ftp://g.oswego.edu/pub/misc/malloc.c
     Check before installing!
* Why use this malloc?
  This is not the fastest, most space-conserving, most portable, or
  most tunable malloc ever written. However it is among the fastest
  while also being among the most space-conserving, portable and tunable.
  Consistent balance across these factors results in a good general-purpose
  allocator. For a high-level description, see
     http://g.oswego.edu/dl/html/malloc.html
* Synopsis of public routines
  (Much fuller descriptions are contained in the program documentation below.)
  malloc(size_t n);
     Return a pointer to a newly allocated chunk of at least n bytes, or null
     if no space is available.
  free(Void_t* p);
     Release the chunk of memory pointed to by p, or no effect if p is null.
  realloc(Void_t* p, size_t n);
     Return a pointer to a chunk of size n that contains the same data
     as does chunk p up to the minimum of (n, p's size) bytes, or null
     if no space is available. The returned pointer may or may not be
     the same as p. If p is null, equivalent to malloc.  Unless the
     #define REALLOC_ZERO_BYTES_FREES below is set, realloc with a
     size argument of zero (re)allocates a minimum-sized chunk.
  memalign(size_t alignment, size_t n);
     Return a pointer to a newly allocated chunk of n bytes, aligned
     in accord with the alignment argument, which must be a power of
     two.
  valloc(size_t n);
     Equivalent to memalign(pagesize, n), where pagesize is the page
     size of the system (or as near to this as can be figured out from
     all the includes/defines below.)
  pvalloc(size_t n);
     Equivalent to valloc(minimum-page-that-holds(n)), that is,
     round up n to nearest pagesize.
  calloc(size_t unit, size_t quantity);
     Returns a pointer to quantity * unit bytes, with all locations
     set to zero.
  cfree(Void_t* p);
     Equivalent to free(p).
  malloc_trim(size_t pad);
     Release all but pad bytes of freed top-most memory back
     to the system. Return 1 if successful, else 0.
  malloc_usable_size(Void_t* p);
     Report the number usable allocated bytes associated with allocated
     chunk p. This may or may not report more bytes than were requested,
     due to alignment and minimum size constraints.
  malloc_stats();
     Prints brief summary statistics on stderr.
  mallinfo()
     Returns (by copy) a struct containing various summary statistics.
  mallopt(int parameter_number, int parameter_value)
     Changes one of the tunable parameters described below. Returns
     1 if successful in changing the parameter, else 0.
* Vital statistics:
  Alignment:                            8-byte
       8 byte alignment is currently hardwired into the design.  This
       seems to suffice for all current machines and C compilers.
  Assumed pointer representation:       4 or 8 bytes
       Code for 8-byte pointers is untested by me but has worked
       reliably by Wolfram Gloger, who contributed most of the
       changes supporting this.
  Assumed size_t  representation:       4 or 8 bytes
       Note that size_t is allowed to be 4 bytes even if pointers are 8.
  Minimum overhead per allocated chunk: 4 or 8 bytes
       Each malloced chunk has a hidden overhead of 4 bytes holding size
       and status information.
  Minimum allocated size: 4-byte ptrs:  16 bytes    (including 4 overhead)
              8-byte ptrs:  24/32 bytes (including, 4/8 overhead)
       When a chunk is freed, 12 (for 4byte ptrs) or 20 (for 8 byte
       ptrs but 4 byte size) or 24 (for 8/8) additional bytes are
       needed; 4 (8) for a trailing size field
       and 8 (16) bytes for free list pointers. Thus, the minimum
       allocatable size is 16/24/32 bytes.
       Even a request for zero bytes (i.e., malloc(0)) returns a
       pointer to something of the minimum allocatable size.
  Maximum allocated size: 4-byte size_t: 2^31 -  8 bytes
              8-byte size_t: 2^63 - 16 bytes
       It is assumed that (possibly signed) size_t bit values suffice to
       represent chunk sizes. `Possibly signed' is due to the fact
       that `size_t' may be defined on a system as either a signed or
       an unsigned type. To be conservative, values that would appear
       as negative numbers are avoided.
       Requests for sizes with a negative sign bit when the request
       size is treaded as a long will return null.
  Maximum overhead wastage per allocated chunk: normally 15 bytes
       Alignnment demands, plus the minimum allocatable size restriction
       make the normal worst-case wastage 15 bytes (i.e., up to 15
       more bytes will be allocated than were requested in malloc), with
       two exceptions:
     1. Because requests for zero bytes allocate non-zero space,
        the worst case wastage for a request of zero bytes is 24 bytes.
     2. For requests >= mmap_threshold that are serviced via
        mmap(), the worst case wastage is 8 bytes plus the remainder
        from a system page (the minimal mmap unit); typically 4096 bytes.
* Limitations
    Here are some features that are NOT currently supported
    * No user-definable hooks for callbacks and the like.
    * No automated mechanism for fully checking that all accesses
      to malloced memory stay within their bounds.
    * No support for compaction.
* Synopsis of compile-time options:
    People have reported using previous versions of this malloc on all
    versions of Unix, sometimes by tweaking some of the defines
    below. It has been tested most extensively on Solaris and
    Linux. It is also reported to work on WIN32 platforms.
    People have also reported adapting this malloc for use in
    stand-alone embedded systems.
    The implementation is in straight, hand-tuned ANSI C.  Among other
    consequences, it uses a lot of macros.  Because of this, to be at
    all usable, this code should be compiled using an optimizing compiler
    (for example gcc -O2) that can simplify expressions and control
    paths.
  __STD_C                  (default: derived from C compiler defines)
     Nonzero if using ANSI-standard C compiler, a C++ compiler, or
     a C compiler sufficiently close to ANSI to get away with it.
  DEBUG                    (default: NOT defined)
     Define to enable debugging. Adds fairly extensive assertion-based
     checking to help track down memory errors, but noticeably slows down
     execution.
  REALLOC_ZERO_BYTES_FREES (default: NOT defined)
     Define this if you think that realloc(p, 0) should be equivalent
     to free(p). Otherwise, since malloc returns a unique pointer for
     malloc(0), so does realloc(p, 0).
  HAVE_MEMCPY               (default: defined)
     Define if you are not otherwise using ANSI STD C, but still
     have memcpy and memset in your C library and want to use them.
     Otherwise, simple internal versions are supplied.
  USE_MEMCPY               (default: 1 if HAVE_MEMCPY is defined, 0 otherwise)
     Define as 1 if you want the C library versions of memset and
     memcpy called in realloc and calloc (otherwise macro versions are used).
     At least on some platforms, the simple macro versions usually
     outperform libc versions.
  HAVE_MMAP                 (default: defined as 1)
     Define to non-zero to optionally make malloc() use mmap() to
     allocate very large blocks.
  HAVE_MREMAP                 (default: defined as 0 unless Linux libc set)
     Define to non-zero to optionally make realloc() use mremap() to
     reallocate very large blocks.
  malloc_getpagesize        (default: derived from system #includes)
     Either a constant or routine call returning the system page size.
  HAVE_USR_INCLUDE_MALLOC_H (default: NOT defined)
     Optionally define if you are on a system with a /usr/include/malloc.h
     that declares struct mallinfo. It is not at all necessary to
     define this even if you do, but will ensure consistency.
  INTERNAL_SIZE_T           (default: size_t)
     Define to a 32-bit type (probably `unsigned int') if you are on a
     64-bit machine, yet do not want or need to allow malloc requests of
     greater than 2^31 to be handled. This saves space, especially for
     very small chunks.
  INTERNAL_LINUX_C_LIB      (default: NOT defined)
     Defined only when compiled as part of Linux libc.
     Also note that there is some odd internal name-mangling via defines
     (for example, internally, `malloc' is named `mALLOc') needed
     when compiling in this case. These look funny but don't otherwise
     affect anything.
  WIN32                     (default: undefined)
     Define this on MS win (95, nt) platforms to compile in sbrk emulation.
  LACKS_UNISTD_H            (default: undefined if not WIN32)
     Define this if your system does not have a <unistd.h>.
  LACKS_SYS_PARAM_H         (default: undefined if not WIN32)
     Define this if your system does not have a <sys/param.h>.
  MORECORE                  (default: sbrk)
     The name of the routine to call to obtain more memory from the system.
  MORECORE_FAILURE          (default: -1)
     The value returned upon failure of MORECORE.
  MORECORE_CLEARS           (default 1)
     true (1) if the routine mapped to MORECORE zeroes out memory (which
     holds for sbrk).
  DEFAULT_TRIM_THRESHOLD
  DEFAULT_TOP_PAD
  DEFAULT_MMAP_THRESHOLD
  DEFAULT_MMAP_MAX
     Default values of tunable parameters (described in detail below)
     controlling interaction with host system routines (sbrk, mmap, etc).
     These values may also be changed dynamically via mallopt(). The
     preset defaults are those that give best performance for typical
     programs/systems.
  USE_DL_PREFIX             (default: undefined)
     Prefix all public routines with the string 'dl'.  Useful to
     quickly avoid procedure declaration conflicts and linker symbol
     conflicts with existing memory allocation routines.
*/
#ifndef __MALLOC_H__
#define __MALLOC_H__
/* Preliminaries */
#ifndef __STD_C
#ifdef __STDC__
#define __STD_C     1
#else
#if __cplusplus
#define __STD_C     1
#else
#define __STD_C     0
#endif /*__cplusplus*/
#endif /*__STDC__*/
#endif /*__STD_C*/
#ifndef Void_t
#if (__STD_C || defined(WIN32))
#define Void_t      void
#else
#define Void_t      char
#endif
#endif /*Void_t*/
#if __STD_C
#include <types.h>    /* for size_t */
#else
#include <sys/types.h>
#endif    /* __STD_C */
#ifdef __cplusplus
extern "C" {
#endif
#define assert(x) ((void)0)
#if 0    /* not for U-Boot */
#include <stdio.h>    /* needed for malloc_stats */
#endif
/*
  Compile-time options
*/
/*
    Debugging:
    Because freed chunks may be overwritten with link fields, this
    malloc will often die when freed memory is overwritten by user
    programs.  This can be very effective (albeit in an annoying way)
    in helping track down dangling pointers.
    If you compile with -DDEBUG, a number of assertion checks are
    enabled that will catch more memory errors. You probably won't be
    able to make much sense of the actual assertion errors, but they
    should help you locate incorrectly overwritten memory.  The
    checking is fairly extensive, and will slow down execution
    noticeably. Calling malloc_stats or mallinfo with DEBUG set will
    attempt to check every non-mmapped allocated and free chunk in the
    course of computing the summmaries. (By nature, mmapped regions
    cannot be checked very much automatically.)
    Setting DEBUG may also be helpful if you are trying to modify
    this code. The assertions in the check routines spell out in more
    detail the assumptions and invariants underlying the algorithms.
*/
/*
  INTERNAL_SIZE_T is the word-size used for internal bookkeeping
  of chunk sizes. On a 64-bit machine, you can reduce malloc
  overhead by defining INTERNAL_SIZE_T to be a 32 bit `unsigned int'
  at the expense of not being able to handle requests greater than
  2^31. This limitation is hardly ever a concern; you are encouraged
  to set this. However, the default version is the same as size_t.
*/
#ifndef INTERNAL_SIZE_T
#define INTERNAL_SIZE_T size_t
#endif
/*
  REALLOC_ZERO_BYTES_FREES should be set if a call to
  realloc with zero bytes should be the same as a call to free.
  Some people think it should. Otherwise, since this malloc
  returns a unique pointer for malloc(0), so does realloc(p, 0).
*/
/*   #define REALLOC_ZERO_BYTES_FREES */
/*
  WIN32 causes an emulation of sbrk to be compiled in
  mmap-based options are not currently supported in WIN32.
*/
/* #define WIN32 */
#ifdef WIN32
#define MORECORE wsbrk
#define HAVE_MMAP 0
#define LACKS_UNISTD_H
#define LACKS_SYS_PARAM_H
/*
  Include 'windows.h' to get the necessary declarations for the
  Microsoft Visual C++ data structures and routines used in the 'sbrk'
  emulation.
  Define WIN32_LEAN_AND_MEAN so that only the essential Microsoft
  Visual C++ header files are included.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
/*
  HAVE_MEMCPY should be defined if you are not otherwise using
  ANSI STD C, but still have memcpy and memset in your C library
  and want to use them in calloc and realloc. Otherwise simple
  macro versions are defined here.
  USE_MEMCPY should be defined as 1 if you actually want to
  have memset and memcpy called. People report that the macro
  versions are often enough faster than libc versions on many
  systems that it is better to use them.
*/
#define HAVE_MEMCPY
#ifndef USE_MEMCPY
#ifdef HAVE_MEMCPY
#define USE_MEMCPY 1
#else
#define USE_MEMCPY 0
#endif
#endif
#if (__STD_C || defined(HAVE_MEMCPY))
#if __STD_C
void* memset(void*, int, size_t);
void* memcpy(void*, const void*, size_t);
#else
#ifdef WIN32
/* On Win32 platforms, 'memset()' and 'memcpy()' are already declared in */
/* 'windows.h' */
#else
Void_t* memset();
Void_t* memcpy();
#endif
#endif
#endif
#if USE_MEMCPY
/* The following macros are only invoked with (2n+1)-multiples of
   INTERNAL_SIZE_T units, with a positive integer n. This is exploited
   for fast inline execution when n is small. */
#define MALLOC_ZERO(charp, nbytes)                                            \
do {                                                                          \
  INTERNAL_SIZE_T mzsz = (nbytes);                                            \
  if(mzsz <= 9*sizeof(mzsz)) {                                                \
    INTERNAL_SIZE_T* mz = (INTERNAL_SIZE_T*) (charp);                         \
    if(mzsz >= 5*sizeof(mzsz)) {     *mz++ = 0;                               \
                     *mz++ = 0;                               \
      if(mzsz >= 7*sizeof(mzsz)) {   *mz++ = 0;                               \
                     *mz++ = 0;                               \
    if(mzsz >= 9*sizeof(mzsz)) { *mz++ = 0;                               \
                     *mz++ = 0; }}}                           \
                     *mz++ = 0;                               \
                     *mz++ = 0;                               \
                     *mz   = 0;                               \
  } else memset((charp), 0, mzsz);                                            \
} while(0)
#define MALLOC_COPY(dest,src,nbytes)                                          \
do {                                                                          \
  INTERNAL_SIZE_T mcsz = (nbytes);                                            \
  if(mcsz <= 9*sizeof(mcsz)) {                                                \
    INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) (src);                        \
    INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) (dest);                       \
    if(mcsz >= 5*sizeof(mcsz)) {     *mcdst++ = *mcsrc++;                     \
                     *mcdst++ = *mcsrc++;                     \
      if(mcsz >= 7*sizeof(mcsz)) {   *mcdst++ = *mcsrc++;                     \
                     *mcdst++ = *mcsrc++;                     \
    if(mcsz >= 9*sizeof(mcsz)) { *mcdst++ = *mcsrc++;                     \
                     *mcdst++ = *mcsrc++; }}}                 \
                     *mcdst++ = *mcsrc++;                     \
                     *mcdst++ = *mcsrc++;                     \
                     *mcdst   = *mcsrc  ;                     \
  } else memcpy(dest, src, mcsz);                                             \
} while(0)
#else /* !USE_MEMCPY */
/* Use Duff's device for good zeroing/copying performance. */
#define MALLOC_ZERO(charp, nbytes)                                            \
do {                                                                          \
  INTERNAL_SIZE_T* mzp = (INTERNAL_SIZE_T*)(charp);                           \
  long mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T), mcn;                         \
  if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; }             \
  switch (mctmp) {                                                            \
    case 0: for(;;) { *mzp++ = 0;                                             \
    case 7:           *mzp++ = 0;                                             \
    case 6:           *mzp++ = 0;                                             \
    case 5:           *mzp++ = 0;                                             \
    case 4:           *mzp++ = 0;                                             \
    case 3:           *mzp++ = 0;                                             \
    case 2:           *mzp++ = 0;                                             \
    case 1:           *mzp++ = 0; if(mcn <= 0) break; mcn--; }                \
  }                                                                           \
} while(0)
#define MALLOC_COPY(dest,src,nbytes)                                          \
do {                                                                          \
  INTERNAL_SIZE_T* mcsrc = (INTERNAL_SIZE_T*) src;                            \
  INTERNAL_SIZE_T* mcdst = (INTERNAL_SIZE_T*) dest;                           \
  long mctmp = (nbytes)/sizeof(INTERNAL_SIZE_T), mcn;                         \
  if (mctmp < 8) mcn = 0; else { mcn = (mctmp-1)/8; mctmp %= 8; }             \
  switch (mctmp) {                                                            \
    case 0: for(;;) { *mcdst++ = *mcsrc++;                                    \
    case 7:           *mcdst++ = *mcsrc++;                                    \
    case 6:           *mcdst++ = *mcsrc++;                                    \
    case 5:           *mcdst++ = *mcsrc++;                                    \
    case 4:           *mcdst++ = *mcsrc++;                                    \
    case 3:           *mcdst++ = *mcsrc++;                                    \
    case 2:           *mcdst++ = *mcsrc++;                                    \
    case 1:           *mcdst++ = *mcsrc++; if(mcn <= 0) break; mcn--; }       \
  }                                                                           \
} while(0)
#endif
/*
  Define HAVE_MMAP to optionally make malloc() use mmap() to
  allocate very large blocks.  These will be returned to the
  operating system immediately after a free().
*/
/***
#ifndef HAVE_MMAP
#define HAVE_MMAP 1
#endif
***/
#undef    HAVE_MMAP    /* Not available for U-Boot */
/*
  Define HAVE_MREMAP to make realloc() use mremap() to re-allocate
  large blocks.  This is currently only possible on Linux with
  kernel versions newer than 1.3.77.
*/
/***
#ifndef HAVE_MREMAP
#ifdef INTERNAL_LINUX_C_LIB
#define HAVE_MREMAP 1
#else
#define HAVE_MREMAP 0
#endif
#endif
***/
#undef    HAVE_MREMAP    /* Not available for U-Boot */
#ifdef HAVE_MMAP
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
#define MAP_ANONYMOUS MAP_ANON
#endif
#endif /* HAVE_MMAP */
/*
  Access to system page size. To the extent possible, this malloc
  manages memory from the system in page-size units.
  The following mechanics for getpagesize were adapted from
  bsd/gnu getpagesize.h
*/
#define    LACKS_UNISTD_H    /* Shortcut for U-Boot */
#define    malloc_getpagesize    4096
#ifndef LACKS_UNISTD_H
#  include <unistd.h>
#endif
#ifndef malloc_getpagesize
#  ifdef _SC_PAGESIZE         /* some SVR4 systems omit an underscore */
#    ifndef _SC_PAGE_SIZE
#      define _SC_PAGE_SIZE _SC_PAGESIZE
#    endif
#  endif
#  ifdef _SC_PAGE_SIZE
#    define malloc_getpagesize sysconf(_SC_PAGE_SIZE)
#  else
#    if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE)
       extern size_t getpagesize();
#      define malloc_getpagesize getpagesize()
#    else
#      ifdef WIN32
#        define malloc_getpagesize (4096) /* TBD: Use 'GetSystemInfo' instead */
#      else
#        ifndef LACKS_SYS_PARAM_H
#          include <sys/param.h>
#        endif
#        ifdef EXEC_PAGESIZE
#          define malloc_getpagesize EXEC_PAGESIZE
#        else
#          ifdef NBPG
#            ifndef CLSIZE
#              define malloc_getpagesize NBPG
#            else
#              define malloc_getpagesize (NBPG * CLSIZE)
#            endif
#          else
#            ifdef NBPC
#              define malloc_getpagesize NBPC
#            else
#              ifdef PAGESIZE
#                define malloc_getpagesize PAGESIZE
#              else
#                define malloc_getpagesize (4096) /* just guess */
#              endif
#            endif
#          endif
#        endif
#      endif
#    endif
#  endif
#endif
/*
  This version of malloc supports the standard SVID/XPG mallinfo
  routine that returns a struct containing the same kind of
  information you can get from malloc_stats. It should work on
  any SVID/XPG compliant system that has a /usr/include/malloc.h
  defining struct mallinfo. (If you'd like to install such a thing
  yourself, cut out the preliminary declarations as described above
  and below and save them in a malloc.h file. But there's no
  compelling reason to bother to do this.)
  The main declaration needed is the mallinfo struct that is returned
  (by-copy) by mallinfo().  The SVID/XPG malloinfo struct contains a
  bunch of fields, most of which are not even meaningful in this
  version of malloc. Some of these fields are are instead filled by
  mallinfo() with other numbers that might possibly be of interest.
  HAVE_USR_INCLUDE_MALLOC_H should be set if you have a
  /usr/include/malloc.h file that includes a declaration of struct
  mallinfo.  If so, it is included; else an SVID2/XPG2 compliant
  version is declared below.  These must be precisely the same for
  mallinfo() to work.
*/
/* #define HAVE_USR_INCLUDE_MALLOC_H */
#ifdef HAVE_USR_INCLUDE_MALLOC_H
#include "/usr/include/malloc.h"
#else
/* SVID2/XPG mallinfo structure */
struct mallinfo {
  int arena;    /* total space allocated from system */
  int ordblks;  /* number of non-inuse chunks */
  int smblks;   /* unused -- always zero */
  int hblks;    /* number of mmapped regions */
  int hblkhd;   /* total space in mmapped regions */
  int usmblks;  /* unused -- always zero */
  int fsmblks;  /* unused -- always zero */
  int uordblks; /* total allocated space */
  int fordblks; /* total non-inuse space */
  int keepcost; /* top-most, releasable (via malloc_trim) space */
};
/* SVID2/XPG mallopt options */
#define M_MXFAST  1    /* UNUSED in this malloc */
#define M_NLBLKS  2    /* UNUSED in this malloc */
#define M_GRAIN   3    /* UNUSED in this malloc */
#define M_KEEP    4    /* UNUSED in this malloc */
#endif
/* mallopt options that actually do something */
#define M_TRIM_THRESHOLD    -1
#define M_TOP_PAD           -2
#define M_MMAP_THRESHOLD    -3
#define M_MMAP_MAX          -4
#ifndef DEFAULT_TRIM_THRESHOLD
#define DEFAULT_TRIM_THRESHOLD (128 * 1024)
#endif
/*
    M_TRIM_THRESHOLD is the maximum amount of unused top-most memory
      to keep before releasing via malloc_trim in free().
      Automatic trimming is mainly useful in long-lived programs.
      Because trimming via sbrk can be slow on some systems, and can
      sometimes be wasteful (in cases where programs immediately
      afterward allocate more large chunks) the value should be high
      enough so that your overall system performance would improve by
      releasing.
      The trim threshold and the mmap control parameters (see below)
      can be traded off with one another. Trimming and mmapping are
      two different ways of releasing unused memory back to the
      system. Between these two, it is often possible to keep
      system-level demands of a long-lived program down to a bare
      minimum. For example, in one test suite of sessions measuring
      the XF86 X server on Linux, using a trim threshold of 128K and a
      mmap threshold of 192K led to near-minimal long term resource
      consumption.
      If you are using this malloc in a long-lived program, it should
      pay to experiment with these values.  As a rough guide, you
      might set to a value close to the average size of a process
      (program) running on your system.  Releasing this much memory
      would allow such a process to run in memory.  Generally, it's
      worth it to tune for trimming rather tham memory mapping when a
      program undergoes phases where several large chunks are
      allocated and released in ways that can reuse each other's
      storage, perhaps mixed with phases where there are no such
      chunks at all.  And in well-behaved long-lived programs,
      controlling release of large blocks via trimming versus mapping
      is usually faster.
      However, in most programs, these parameters serve mainly as
      protection against the system-level effects of carrying around
      massive amounts of unneeded memory. Since frequent calls to
      sbrk, mmap, and munmap otherwise degrade performance, the default
      parameters are set to relatively high values that serve only as
      safeguards.
      The default trim value is high enough to cause trimming only in
      fairly extreme (by current memory consumption standards) cases.
      It must be greater than page size to have any useful effect.  To
      disable trimming completely, you can set to (unsigned long)(-1);
*/
#ifndef DEFAULT_TOP_PAD
#define DEFAULT_TOP_PAD        (0)
#endif
/*
    M_TOP_PAD is the amount of extra `padding' space to allocate or
      retain whenever sbrk is called. It is used in two ways internally:
      * When sbrk is called to extend the top of the arena to satisfy
    a new malloc request, this much padding is added to the sbrk
    request.
      * When malloc_trim is called automatically from free(),
    it is used as the `pad' argument.
      In both cases, the actual amount of padding is rounded
      so that the end of the arena is always a system page boundary.
      The main reason for using padding is to avoid calling sbrk so
      often. Having even a small pad greatly reduces the likelihood
      that nearly every malloc request during program start-up (or
      after trimming) will invoke sbrk, which needlessly wastes
      time.
      Automatic rounding-up to page-size units is normally sufficient
      to avoid measurable overhead, so the default is 0.  However, in
      systems where sbrk is relatively slow, it can pay to increase
      this value, at the expense of carrying around more memory than
      the program needs.
*/
#ifndef DEFAULT_MMAP_THRESHOLD
#define DEFAULT_MMAP_THRESHOLD (128 * 1024)
#endif
/*
    M_MMAP_THRESHOLD is the request size threshold for using mmap()
      to service a request. Requests of at least this size that cannot
      be allocated using already-existing space will be serviced via mmap.
      (If enough normal freed space already exists it is used instead.)
      Using mmap segregates relatively large chunks of memory so that
      they can be individually obtained and released from the host
      system. A request serviced through mmap is never reused by any
      other request (at least not directly; the system may just so
      happen to remap successive requests to the same locations).
      Segregating space in this way has the benefit that mmapped space
      can ALWAYS be individually released back to the system, which
      helps keep the system level memory demands of a long-lived
      program low. Mapped memory can never become `locked' between
      other chunks, as can happen with normally allocated chunks, which
      menas that even trimming via malloc_trim would not release them.
      However, it has the disadvantages that:
     1. The space cannot be reclaimed, consolidated, and then
        used to service later requests, as happens with normal chunks.
     2. It can lead to more wastage because of mmap page alignment
        requirements
     3. It causes malloc performance to be more dependent on host
        system memory management support routines which may vary in
        implementation quality and may impose arbitrary
        limitations. Generally, servicing a request via normal
        malloc steps is faster than going through a system's mmap.
      All together, these considerations should lead you to use mmap
      only for relatively large requests.
*/
#ifndef DEFAULT_MMAP_MAX
#ifdef HAVE_MMAP
#define DEFAULT_MMAP_MAX       (64)
#else
#define DEFAULT_MMAP_MAX       (0)
#endif
#endif
/*
    M_MMAP_MAX is the maximum number of requests to simultaneously
      service using mmap. This parameter exists because:
     1. Some systems have a limited number of internal tables for
        use by mmap.
     2. In most systems, overreliance on mmap can degrade overall
        performance.
     3. If a program allocates many large regions, it is probably
        better off using normal sbrk-based allocation routines that
        can reclaim and reallocate normal heap memory. Using a
        small value allows transition into this mode after the
        first few allocations.
      Setting to 0 disables all use of mmap.  If HAVE_MMAP is not set,
      the default value is 0, and attempts to set it to non-zero values
      in mallopt will fail.
*/
/*
    USE_DL_PREFIX will prefix all public routines with the string 'dl'.
      Useful to quickly avoid procedure declaration conflicts and linker
      symbol conflicts with existing memory allocation routines.
*/
/* #define USE_DL_PREFIX */
/*
  Special defines for linux libc
  Except when compiled using these special defines for Linux libc
  using weak aliases, this malloc is NOT designed to work in
  multithreaded applications.  No semaphores or other concurrency
  control are provided to ensure that multiple malloc or free calls
  don't run at the same time, which could be disasterous. A single
  semaphore could be used across malloc, realloc, and free (which is
  essentially the effect of the linux weak alias approach). It would
  be hard to obtain finer granularity.
*/
#ifdef INTERNAL_LINUX_C_LIB
#if __STD_C
Void_t * __default_morecore_init (ptrdiff_t);
Void_t *(*__morecore)(ptrdiff_t) = __default_morecore_init;
#else
Void_t * __default_morecore_init ();
Void_t *(*__morecore)() = __default_morecore_init;
#endif
#define MORECORE (*__morecore)
#define MORECORE_FAILURE 0
#define MORECORE_CLEARS 1
#else /* INTERNAL_LINUX_C_LIB */
#if __STD_C
extern Void_t*     sbrk(ptrdiff_t);
#else
extern Void_t*     sbrk();
#endif
#ifndef MORECORE
#define MORECORE sbrk
#endif
#ifndef MORECORE_FAILURE
#define MORECORE_FAILURE -1
#endif
#ifndef MORECORE_CLEARS
#define MORECORE_CLEARS 1
#endif
#endif /* INTERNAL_LINUX_C_LIB */
#if defined(INTERNAL_LINUX_C_LIB) && defined(__ELF__)
#define cALLOc        __libc_calloc
#define fREe        __libc_free
#define mALLOc        __libc_malloc
#define mEMALIGn    __libc_memalign
#define rEALLOc        __libc_realloc
#define vALLOc        __libc_valloc
#define pvALLOc        __libc_pvalloc
#define mALLINFo    __libc_mallinfo
#define mALLOPt        __libc_mallopt
#pragma weak calloc = __libc_calloc
#pragma weak free = __libc_free
#pragma weak cfree = __libc_free
#pragma weak malloc = __libc_malloc
#pragma weak memalign = __libc_memalign
#pragma weak realloc = __libc_realloc
#pragma weak valloc = __libc_valloc
#pragma weak pvalloc = __libc_pvalloc
#pragma weak mallinfo = __libc_mallinfo
#pragma weak mallopt = __libc_mallopt
#else
#ifdef USE_DL_PREFIX
#define cALLOc        dlcalloc
#define fREe        dlfree
#define mALLOc        dlmalloc
#define mEMALIGn    dlmemalign
#define rEALLOc        dlrealloc
#define vALLOc        dlvalloc
#define pvALLOc        dlpvalloc
#define mALLINFo    dlmallinfo
#define mALLOPt        dlmallopt
#else /* USE_DL_PREFIX */
#define cALLOc        calloc
#define fREe        free
#define mALLOc        malloc
#define mEMALIGn    memalign
#define rEALLOc        realloc
#define vALLOc        valloc
#define pvALLOc        pvalloc
#define mALLINFo    mallinfo
#define mALLOPt        mallopt
#endif /* USE_DL_PREFIX */
#endif
/* Public routines */
#if __STD_C
Void_t* mALLOc(size_t);
void    fREe(Void_t*);
Void_t* rEALLOc(Void_t*, size_t);
Void_t* mEMALIGn(size_t, size_t);
Void_t* vALLOc(size_t);
Void_t* pvALLOc(size_t);
Void_t* cALLOc(size_t, size_t);
void    cfree(Void_t*);
int     malloc_trim(size_t);
size_t  malloc_usable_size(Void_t*);
void    malloc_stats(void);
int     mALLOPt(int, int);
struct mallinfo mALLINFo(void);
#else
Void_t* mALLOc();
void    fREe();
Void_t* rEALLOc();
Void_t* mEMALIGn();
Void_t* vALLOc();
Void_t* pvALLOc();
Void_t* cALLOc();
void    cfree();
int     malloc_trim();
size_t  malloc_usable_size();
void    malloc_stats();
int     mALLOPt();
struct mallinfo mALLINFo();
#endif
/*
 * Begin and End of memory area for malloc(), and current "brk"
 */
extern ulong mem_malloc_start;
extern ulong mem_malloc_end;
extern ulong mem_malloc_brk;
void mem_malloc_init(ulong start, ulong size);
#ifdef __cplusplus
};  /* end of extern "C" */
#endif
#endif /* __MALLOC_H__ */
linux-bsp/asm-study/yaffs2/common/printf.c
New file
@@ -0,0 +1,374 @@
/*
 *  linux/lib/vsprintf.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 */
/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
/*
 * Wirzenius wrote this portably, Torvalds fucked it up :-)
 */
#include <stdio.h>
#include <string.h>
#include "s3c_board.h"
#define CFG_PBSIZE                  1024 /*  Print Buffer Size */
#define is_digit(c)    ((c) >= '0' && (c) <= '9')
static int skip_atoi(const char **s)
{
    int i = 0;
    while (is_digit(**s))
        i = i * 10 + *((*s)++) - '0';
    return i;
}
#define ZEROPAD    1               /* pad with zero */
#define SIGN    2               /* unsigned/signed long */
#define PLUS    4               /* show plus */
#define SPACE    8               /* space if plus */
#define LEFT    16              /* left justified */
#define SPECIAL    32              /* 0x */
#define LARGE    64              /* use 'ABCDEF' instead of 'abcdef' */
#ifdef CFG_64BIT_VSPRINTF
#define do_div(n,base) ({ \
    unsigned int __res; \
    __res = ((unsigned long long) n) % base; \
    n = ((unsigned long long) n) / base; \
    __res; \
})
#else
#define do_div(n,base) ({ \
    int __res; \
    __res = ((unsigned long) n) % base; \
    n = ((unsigned long) n) / base; \
    __res; \
})
#endif
#ifdef CFG_64BIT_VSPRINTF
static char *number(char *str, long long num, unsigned int base, int size, int precision, int type)
#else
static char *number(char *str, long num, unsigned int base, int size, int precision, int type)
#endif
{
    char c, sign, tmp[66];
    const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
    int i;
    if (type & LARGE)
        digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    if (type & LEFT)
        type &= ~ZEROPAD;
    if (base < 2 || base > 36)
        return 0;
    c = (type & ZEROPAD) ? '0' : ' ';
    sign = 0;
    if (type & SIGN)
    {
        if (num < 0)
        {
            sign = '-';
            num = -num;
            size--;
        }
        else if (type & PLUS)
        {
            sign = '+';
            size--;
        }
        else if (type & SPACE)
        {
            sign = ' ';
            size--;
        }
    }
    if (type & SPECIAL)
    {
        if (base == 16)
            size -= 2;
        else if (base == 8)
            size--;
    }
    i = 0;
    if (num == 0)
        tmp[i++] = '0';
    else
        while (num != 0)
            tmp[i++] = digits[do_div(num, base)];
    if (i > precision)
        precision = i;
    size -= precision;
    if (!(type & (ZEROPAD + LEFT)))
        while (size-- > 0)
            *str++ = ' ';
    if (sign)
        *str++ = sign;
    if (type & SPECIAL)
    {
        if (base == 8)
            *str++ = '0';
        else if (base == 16)
        {
            *str++ = '0';
            *str++ = digits[33];
        }
    }
    if (!(type & LEFT))
        while (size-- > 0)
            *str++ = c;
    while (i < precision--)
        *str++ = '0';
    while (i-- > 0)
        *str++ = tmp[i];
    while (size-- > 0)
        *str++ = ' ';
    return str;
}
/* Forward decl. needed for IP address printing stuff... */
int sprintf(char *buf, const char *fmt, ...);
int vsprintf(char *buf, const char *fmt, va_list args)
{
    int len;
#ifdef CFG_64BIT_VSPRINTF
    unsigned long long num;
#else
    unsigned long num;
#endif
    int i, base;
    char *str;
    const char *s;
    int flags;                  /* flags to number() */
    int field_width;            /* width of output field */
    int precision;              /* min. # of digits for integers; max
                                 * number of chars for from string */
    int qualifier;              /* 'h', 'l', or 'q' for integer fields */
    for (str = buf; *fmt; ++fmt)
    {
        if (*fmt != '%')
        {
            *str++ = *fmt;
            continue;
        }
        /* process flags */
        flags = 0;
      repeat:
        ++fmt;                  /* this also skips first '%' */
        switch (*fmt)
        {
          case '-':
              flags |= LEFT;
              goto repeat;
          case '+':
              flags |= PLUS;
              goto repeat;
          case ' ':
              flags |= SPACE;
              goto repeat;
          case '#':
              flags |= SPECIAL;
              goto repeat;
          case '0':
              flags |= ZEROPAD;
              goto repeat;
        }
        /* get field width */
        field_width = -1;
        if (is_digit(*fmt))
            field_width = skip_atoi(&fmt);
        else if (*fmt == '*')
        {
            ++fmt;
            /* it's the next argument */
            field_width = va_arg(args, int);
            if (field_width < 0)
            {
                field_width = -field_width;
                flags |= LEFT;
            }
        }
        /* get the precision */
        precision = -1;
        if (*fmt == '.')
        {
            ++fmt;
            if (is_digit(*fmt))
                precision = skip_atoi(&fmt);
            else if (*fmt == '*')
            {
                ++fmt;
                /* it's the next argument */
                precision = va_arg(args, int);
            }
            if (precision < 0)
                precision = 0;
        }
        /* get the conversion qualifier */
        qualifier = -1;
        if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' ||
            *fmt == 'Z' || *fmt == 'z' || *fmt == 't' || *fmt == 'q')
        {
            qualifier = *fmt;
            if (qualifier == 'l' && *(fmt + 1) == 'l')
            {
                qualifier = 'q';
                ++fmt;
            }
            ++fmt;
        }
        /* default base */
        base = 10;
        switch (*fmt)
        {
          case 'c':
              if (!(flags & LEFT))
                  while (--field_width > 0)
                      *str++ = ' ';
              *str++ = (unsigned char)va_arg(args, int);
              while (--field_width > 0)
                  *str++ = ' ';
              continue;
          case 's':
              s = va_arg(args, char *);
              if (!s)
                  s = "<NULL>";
              len = strnlen(s, precision);
              if (!(flags & LEFT))
                  while (len < field_width--)
                      *str++ = ' ';
              for (i = 0; i < len; ++i)
                  *str++ = *s++;
              while (len < field_width--)
                  *str++ = ' ';
              continue;
          case 'p':
              if (field_width == -1)
              {
                  field_width = 2 * sizeof(void *);
                  flags |= ZEROPAD;
              }
              str = number(str,
                           (unsigned long)va_arg(args, void *), 16, field_width, precision, flags);
              continue;
          case 'n':
              if (qualifier == 'l')
              {
                  long *ip = va_arg(args, long *);
                  *ip = (str - buf);
              }
              else
              {
                  int *ip = va_arg(args, int *);
                  *ip = (str - buf);
              }
              continue;
          case '%':
              *str++ = '%';
              continue;
              /* integer number formats - set up the flags and "break" */
          case 'o':
              base = 8;
              break;
          case 'X':
              flags |= LARGE;
          case 'x':
              base = 16;
              break;
          case 'd':
          case 'i':
              flags |= SIGN;
          case 'u':
              break;
          default:
              *str++ = '%';
              if (*fmt)
                  *str++ = *fmt;
              else
                  --fmt;
              continue;
        }
#ifdef CFG_64BIT_VSPRINTF
        if (qualifier == 'q')   /* "quad" for 64 bit variables */
            num = va_arg(args, unsigned long long);
        else
#endif
        if (qualifier == 'l')
        {
            num = va_arg(args, unsigned long);
        }
        else if (qualifier == 'Z' || qualifier == 'z')
        {
            num = va_arg(args, size_t);
        }
        else if (qualifier == 't')
        {
            num = va_arg(args, ptrdiff_t);
        }
        else if (qualifier == 'h')
        {
            num = (unsigned short)va_arg(args, int);
            if (flags & SIGN)
                num = (short)num;
        }
        else if (flags & SIGN)
            num = va_arg(args, int);
        else
            num = va_arg(args, unsigned int);
        str = number(str, num, base, field_width, precision, flags);
    }
    *str = '\0';
    return str - buf;
}
void printf(const char *fmt, ...)
{
    va_list args;
    uint i;
    char printbuffer[CFG_PBSIZE];
    va_start(args, fmt);
    /* For this to work, printbuffer must be larger than
     * anything we ever want to print.
     */
    i = vsprintf(printbuffer, fmt, args);
    va_end(args);
    console_serial_puts(printbuffer);
}
int sprintf(char *buf, const char *fmt, ...)
{
    va_list args;
    int i;
    va_start(args, fmt);
    i = vsprintf(buf, fmt, args);
    va_end(args);
    return i;
}
linux-bsp/asm-study/yaffs2/common/stdio.h
New file
@@ -0,0 +1,32 @@
/********************************************************************************************
 *        File:  common.h
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  A busy head file
 *   ChangeLog:  1, Release initial version on "Tue Jul 12 16:43:18 CST 2011"
 *
 *******************************************************************************************/
#ifndef __COMMON_H
#define __COMMON_H
#include <stdarg.h>
#include <types.h>
#ifdef DEBUG
#define dbg_print(format,args...) printf(format, ##args)
#else
#define dbg_print(format,args...) do{} while(0);
#endif
void serial_init(void);
void serial_send_byte(char c);
int serial_is_recv_enable(void);
int serial_recv_byte(void);
void serial_puts(const char *s);
/*Define in printf.c*/
void printf(const char *fmt, ...);
int sprintf(char *buf, const char *fmt, ...);
#endif
linux-bsp/asm-study/yaffs2/common/string.c
New file
@@ -0,0 +1,603 @@
/*
 *  linux/lib/string.c
 *
 *  Copyright (C) 1991, 1992  Linus Torvalds
 */
/*
 * stupid library routines.. The optimized versions should generally be found
 * as inline code in <asm-xx/string.h>
 *
 * These are buggy as well..
 *
 * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de>
 * -  Added strsep() which will replace strtok() soon (because strsep() is
 *    reentrant and should be faster). Use only strsep() in new code, please.
 */
#include <types.h>
#include <malloc.h>
#if 0 /* not used - was: #ifndef __HAVE_ARCH_STRNICMP */
/**
 * strnicmp - Case insensitive, length-limited string comparison
 * @s1: One string
 * @s2: The other string
 * @len: the maximum number of characters to compare
 */
int strnicmp(const char *s1, const char *s2, size_t len)
{
    /* Yes, Virginia, it had better be unsigned */
    unsigned char c1, c2;
    c1 = 0;    c2 = 0;
    if (len) {
        do {
            c1 = *s1; c2 = *s2;
            s1++; s2++;
            if (!c1)
                break;
            if (!c2)
                break;
            if (c1 == c2)
                continue;
            c1 = tolower(c1);
            c2 = tolower(c2);
            if (c1 != c2)
                break;
        } while (--len);
    }
    return (int)c1 - (int)c2;
}
#endif
char * ___strtok;
#ifndef __HAVE_ARCH_STRCPY
/**
 * strcpy - Copy a %NUL terminated string
 * @dest: Where to copy the string to
 * @src: Where to copy the string from
 */
char * strcpy(char * dest,const char *src)
{
    char *tmp = dest;
    while ((*dest++ = *src++) != '\0')
        /* nothing */;
    return tmp;
}
#endif
#ifndef __HAVE_ARCH_STRNCPY
/**
 * strncpy - Copy a length-limited, %NUL-terminated string
 * @dest: Where to copy the string to
 * @src: Where to copy the string from
 * @count: The maximum number of bytes to copy
 *
 * Note that unlike userspace strncpy, this does not %NUL-pad the buffer.
 * However, the result is not %NUL-terminated if the source exceeds
 * @count bytes.
 */
char * strncpy(char * dest,const char *src,size_t count)
{
    char *tmp = dest;
    while (count-- && (*dest++ = *src++) != '\0')
        /* nothing */;
    return tmp;
}
#endif
#ifndef __HAVE_ARCH_STRCAT
/**
 * strcat - Append one %NUL-terminated string to another
 * @dest: The string to be appended to
 * @src: The string to append to it
 */
char * strcat(char * dest, const char * src)
{
    char *tmp = dest;
    while (*dest)
        dest++;
    while ((*dest++ = *src++) != '\0')
        ;
    return tmp;
}
#endif
#ifndef __HAVE_ARCH_STRNCAT
/**
 * strncat - Append a length-limited, %NUL-terminated string to another
 * @dest: The string to be appended to
 * @src: The string to append to it
 * @count: The maximum numbers of bytes to copy
 *
 * Note that in contrast to strncpy, strncat ensures the result is
 * terminated.
 */
char * strncat(char *dest, const char *src, size_t count)
{
    char *tmp = dest;
    if (count) {
        while (*dest)
            dest++;
        while ((*dest++ = *src++)) {
            if (--count == 0) {
                *dest = '\0';
                break;
            }
        }
    }
    return tmp;
}
#endif
#ifndef __HAVE_ARCH_STRCMP
/**
 * strcmp - Compare two strings
 * @cs: One string
 * @ct: Another string
 */
int strcmp(const char * cs,const char * ct)
{
    register signed char __res;
    while (1) {
        if ((__res = *cs - *ct++) != 0 || !*cs++)
            break;
    }
    return __res;
}
#endif
#ifndef __HAVE_ARCH_STRNCMP
/**
 * strncmp - Compare two length-limited strings
 * @cs: One string
 * @ct: Another string
 * @count: The maximum number of bytes to compare
 */
int strncmp(const char * cs,const char * ct,size_t count)
{
    register signed char __res = 0;
    while (count) {
        if ((__res = *cs - *ct++) != 0 || !*cs++)
            break;
        count--;
    }
    return __res;
}
#endif
#ifndef __HAVE_ARCH_STRCHR
/**
 * strchr - Find the first occurrence of a character in a string
 * @s: The string to be searched
 * @c: The character to search for
 */
char * strchr(const char * s, int c)
{
    for(; *s != (char) c; ++s)
        if (*s == '\0')
            return NULL;
    return (char *) s;
}
#endif
#ifndef __HAVE_ARCH_STRLEN
/**
 * strlen - Find the length of a string
 * @s: The string to be sized
 */
size_t strlen(const char * s)
{
    const char *sc;
    for (sc = s; *sc != '\0'; ++sc)
        /* nothing */;
    return sc - s;
}
#endif
#ifndef __HAVE_ARCH_STRRCHR
/**
 * strrchr - Find the last occurrence of a character in a string
 * @s: The string to be searched
 * @c: The character to search for
 */
char * strrchr(const char * s, int c)
{
       const char *p = s + strlen(s);
       do {
       if (*p == (char)c)
           return (char *)p;
       } while (--p >= s);
       return NULL;
}
#endif
#ifndef __HAVE_ARCH_STRNLEN
/**
 * strnlen - Find the length of a length-limited string
 * @s: The string to be sized
 * @count: The maximum number of bytes to search
 */
size_t strnlen(const char * s, size_t count)
{
    const char *sc;
    for (sc = s; count-- && *sc != '\0'; ++sc)
        /* nothing */;
    return sc - s;
}
#endif
#ifndef __HAVE_ARCH_STRDUP
char * strdup(const char *s)
{
    char *new;
    if ((s == NULL) || ((new = malloc (strlen(s) + 1)) == NULL) )
    {
        return NULL;
    }
    strcpy (new, s);
    return new;
}
#endif
#ifndef __HAVE_ARCH_STRSPN
/**
 * strspn - Calculate the length of the initial substring of @s which only
 *    contain letters in @accept
 * @s: The string to be searched
 * @accept: The string to search for
 */
size_t strspn(const char *s, const char *accept)
{
    const char *p;
    const char *a;
    size_t count = 0;
    for (p = s; *p != '\0'; ++p) {
        for (a = accept; *a != '\0'; ++a) {
            if (*p == *a)
                break;
        }
        if (*a == '\0')
            return count;
        ++count;
    }
    return count;
}
#endif
#ifndef __HAVE_ARCH_STRPBRK
/**
 * strpbrk - Find the first occurrence of a set of characters
 * @cs: The string to be searched
 * @ct: The characters to search for
 */
char * strpbrk(const char * cs,const char * ct)
{
    const char *sc1,*sc2;
    for( sc1 = cs; *sc1 != '\0'; ++sc1) {
        for( sc2 = ct; *sc2 != '\0'; ++sc2) {
            if (*sc1 == *sc2)
                return (char *) sc1;
        }
    }
    return NULL;
}
#endif
#ifndef __HAVE_ARCH_STRTOK
/**
 * strtok - Split a string into tokens
 * @s: The string to be searched
 * @ct: The characters to search for
 *
 * WARNING: strtok is deprecated, use strsep instead.
 */
char * strtok(char * s,const char * ct)
{
    char *sbegin, *send;
    sbegin  = s ? s : ___strtok;
    if (!sbegin) {
        return NULL;
    }
    sbegin += strspn(sbegin,ct);
    if (*sbegin == '\0') {
        ___strtok = NULL;
        return( NULL );
    }
    send = strpbrk( sbegin, ct);
    if (send && *send != '\0')
        *send++ = '\0';
    ___strtok = send;
    return (sbegin);
}
#endif
#ifndef __HAVE_ARCH_STRSEP
/**
 * strsep - Split a string into tokens
 * @s: The string to be searched
 * @ct: The characters to search for
 *
 * strsep() updates @s to point after the token, ready for the next call.
 *
 * It returns empty tokens, too, behaving exactly like the libc function
 * of that name. In fact, it was stolen from glibc2 and de-fancy-fied.
 * Same semantics, slimmer shape. ;)
 */
char * strsep(char **s, const char *ct)
{
    char *sbegin = *s, *end;
    if (sbegin == NULL)
        return NULL;
    end = strpbrk(sbegin, ct);
    if (end)
        *end++ = '\0';
    *s = end;
    return sbegin;
}
#endif
#ifndef __HAVE_ARCH_STRSWAB
/**
 * strswab - swap adjacent even and odd bytes in %NUL-terminated string
 * s: address of the string
 *
 * returns the address of the swapped string or NULL on error. If
 * string length is odd, last byte is untouched.
 */
char *strswab(const char *s)
{
    char *p, *q;
    if ((NULL == s) || ('\0' == *s)) {
        return (NULL);
    }
    for (p=(char *)s, q=p+1; (*p != '\0') && (*q != '\0'); p+=2, q+=2) {
        char  tmp;
        tmp = *p;
        *p  = *q;
        *q  = tmp;
    }
    return (char *) s;
}
#endif
#ifndef __HAVE_ARCH_MEMSET
/**
 * memset - Fill a region of memory with the given value
 * @s: Pointer to the start of the area.
 * @c: The byte to fill the area with
 * @count: The size of the area.
 *
 * Do not use memset() to access IO space, use memset_io() instead.
 */
void * memset(void * s,int c,size_t count)
{
    unsigned long *sl = (unsigned long *) s;
    unsigned long cl = 0;
    char *s8;
    int i;
    /* do it one word at a time (32 bits or 64 bits) while possible */
    if ( ((ulong)s & (sizeof(*sl) - 1)) == 0) {
        for (i = 0; i < sizeof(*sl); i++) {
            cl <<= 8;
            cl |= c & 0xff;
        }
        while (count >= sizeof(*sl)) {
            *sl++ = cl;
            count -= sizeof(*sl);
        }
    }
    /* fill 8 bits at a time */
    s8 = (char *)sl;
    while (count--)
        *s8++ = c;
    return s;
}
#endif
#ifndef __HAVE_ARCH_BCOPY
/**
 * bcopy - Copy one area of memory to another
 * @src: Where to copy from
 * @dest: Where to copy to
 * @count: The size of the area.
 *
 * Note that this is the same as memcpy(), with the arguments reversed.
 * memcpy() is the standard, bcopy() is a legacy BSD function.
 *
 * You should not use this function to access IO space, use memcpy_toio()
 * or memcpy_fromio() instead.
 */
char * bcopy(const char * src, char * dest, int count)
{
    char *tmp = dest;
    while (count--)
        *tmp++ = *src++;
    return dest;
}
#endif
#ifndef __HAVE_ARCH_MEMCPY
/**
 * memcpy - Copy one area of memory to another
 * @dest: Where to copy to
 * @src: Where to copy from
 * @count: The size of the area.
 *
 * You should not use this function to access IO space, use memcpy_toio()
 * or memcpy_fromio() instead.
 */
void * memcpy(void *dest, const void *src, size_t count)
{
    unsigned long *dl = (unsigned long *)dest, *sl = (unsigned long *)src;
    char *d8, *s8;
    /* while all data is aligned (common case), copy a word at a time */
    if ( (((ulong)dest | (ulong)src) & (sizeof(*dl) - 1)) == 0) {
        while (count >= sizeof(*dl)) {
            *dl++ = *sl++;
            count -= sizeof(*dl);
        }
    }
    /* copy the reset one byte at a time */
    d8 = (char *)dl;
    s8 = (char *)sl;
    while (count--)
        *d8++ = *s8++;
    return dest;
}
#endif
#ifndef __HAVE_ARCH_MEMMOVE
/**
 * memmove - Copy one area of memory to another
 * @dest: Where to copy to
 * @src: Where to copy from
 * @count: The size of the area.
 *
 * Unlike memcpy(), memmove() copes with overlapping areas.
 */
void * memmove(void * dest,const void *src,size_t count)
{
    char *tmp, *s;
    if (dest <= src) {
        tmp = (char *) dest;
        s = (char *) src;
        while (count--)
            *tmp++ = *s++;
        }
    else {
        tmp = (char *) dest + count;
        s = (char *) src + count;
        while (count--)
            *--tmp = *--s;
        }
    return dest;
}
#endif
#ifndef __HAVE_ARCH_MEMCMP
/**
 * memcmp - Compare two areas of memory
 * @cs: One area of memory
 * @ct: Another area of memory
 * @count: The size of the area.
 */
int memcmp(const void * cs,const void * ct,size_t count)
{
    const unsigned char *su1, *su2;
    int res = 0;
    for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
        if ((res = *su1 - *su2) != 0)
            break;
    return res;
}
#endif
#ifndef __HAVE_ARCH_MEMSCAN
/**
 * memscan - Find a character in an area of memory.
 * @addr: The memory area
 * @c: The byte to search for
 * @size: The size of the area.
 *
 * returns the address of the first occurrence of @c, or 1 byte past
 * the area if @c is not found
 */
void * memscan(void * addr, int c, size_t size)
{
    unsigned char * p = (unsigned char *) addr;
    while (size) {
        if (*p == c)
            return (void *) p;
        p++;
        size--;
    }
    return (void *) p;
}
#endif
#ifndef __HAVE_ARCH_STRSTR
/**
 * strstr - Find the first substring in a %NUL terminated string
 * @s1: The string to be searched
 * @s2: The string to search for
 */
char * strstr(const char * s1,const char * s2)
{
    int l1, l2;
    l2 = strlen(s2);
    if (!l2)
        return (char *) s1;
    l1 = strlen(s1);
    while (l1 >= l2) {
        l1--;
        if (!memcmp(s1,s2,l2))
            return (char *) s1;
        s1++;
    }
    return NULL;
}
#endif
#ifndef __HAVE_ARCH_MEMCHR
/**
 * memchr - Find a character in an area of memory.
 * @s: The memory area
 * @c: The byte to search for
 * @n: The size of the area.
 *
 * returns the address of the first occurrence of @c, or %NULL
 * if @c is not found
 */
void *memchr(const void *s, int c, size_t n)
{
    const unsigned char *p = s;
    while (n-- != 0) {
        if ((unsigned char)c == *p++) {
            return (void *)(p-1);
        }
    }
    return NULL;
}
#endif
linux-bsp/asm-study/yaffs2/common/string.h
New file
@@ -0,0 +1,86 @@
#ifndef _LINUX_STRING_H_
#define _LINUX_STRING_H_
#include <types.h>    /* for size_t */
#ifdef __cplusplus
extern "C" {
#endif
extern char * ___strtok;
extern char * strpbrk(const char *,const char *);
extern char * strtok(char *,const char *);
extern char * strsep(char **,const char *);
extern __kernel_size_t strspn(const char *,const char *);
/*
 * Include machine specific inline routines
 */
#ifndef __HAVE_ARCH_STRCPY
extern char * strcpy(char *,const char *);
#endif
#ifndef __HAVE_ARCH_STRNCPY
extern char * strncpy(char *,const char *, __kernel_size_t);
#endif
#ifndef __HAVE_ARCH_STRCAT
extern char * strcat(char *, const char *);
#endif
#ifndef __HAVE_ARCH_STRNCAT
extern char * strncat(char *, const char *, __kernel_size_t);
#endif
#ifndef __HAVE_ARCH_STRCMP
extern int strcmp(const char *,const char *);
#endif
#ifndef __HAVE_ARCH_STRNCMP
extern int strncmp(const char *,const char *,__kernel_size_t);
#endif
#if 0 /* not used - was: #ifndef __HAVE_ARCH_STRNICMP */
extern int strnicmp(const char *, const char *, __kernel_size_t);
#endif
#ifndef __HAVE_ARCH_STRCHR
extern char * strchr(const char *,int);
#endif
#ifndef __HAVE_ARCH_STRRCHR
extern char * strrchr(const char *,int);
#endif
#ifndef __HAVE_ARCH_STRSTR
extern char * strstr(const char *,const char *);
#endif
#ifndef __HAVE_ARCH_STRLEN
extern __kernel_size_t strlen(const char *);
#endif
#ifndef __HAVE_ARCH_STRNLEN
extern __kernel_size_t strnlen(const char *,__kernel_size_t);
#endif
#ifndef __HAVE_ARCH_STRDUP
extern char * strdup(const char *);
#endif
#ifndef __HAVE_ARCH_STRSWAB
extern char * strswab(const char *);
#endif
#ifndef __HAVE_ARCH_MEMSET
extern void * memset(void *,int,__kernel_size_t);
#endif
#ifndef __HAVE_ARCH_MEMCPY
extern void * memcpy(void *,const void *,__kernel_size_t);
#endif
#ifndef __HAVE_ARCH_MEMMOVE
extern void * memmove(void *,const void *,__kernel_size_t);
#endif
#ifndef __HAVE_ARCH_MEMSCAN
extern void * memscan(void *,int,__kernel_size_t);
#endif
#ifndef __HAVE_ARCH_MEMCMP
extern int memcmp(const void *,const void *,__kernel_size_t);
#endif
#ifndef __HAVE_ARCH_MEMCHR
extern void * memchr(const void *,int,__kernel_size_t);
#endif
#ifdef __cplusplus
}
#endif
#endif /* _LINUX_STRING_H_ */
linux-bsp/asm-study/yaffs2/common/types.h
New file
@@ -0,0 +1,99 @@
#ifndef _LINUX_TYPES_H
#define _LINUX_TYPES_H
#undef NULL
#if defined(__cplusplus)
#define NULL 0
#else
#define NULL ((void *)0)
#endif
/* bsd */
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned int u_int;
typedef unsigned long u_long;
/* sysv */
typedef unsigned char unchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef unsigned long ulong;
/*
 * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
 * header files exported to user space
 */
typedef __signed__ char __s8;
typedef unsigned char __u8;
typedef __signed__ short __s16;
typedef unsigned short __u16;
typedef __signed__ int __s32;
typedef unsigned int __u32;
#if defined(__GNUC__)
__extension__ typedef __signed__ long long __s64;
__extension__ typedef unsigned long long __u64;
#endif
typedef signed char s8;
typedef unsigned char u8;
typedef signed short s16;
typedef unsigned short u16;
typedef signed int s32;
typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
typedef unsigned int __kernel_size_t;
typedef int __kernel_ssize_t;
typedef int __kernel_ptrdiff_t;
typedef long __kernel_off_t;
typedef long long __kernel_loff_t;
typedef unsigned short __kernel_dev_t;
typedef unsigned short __kernel_mode_t;
typedef __kernel_dev_t dev_t;
typedef __kernel_mode_t mode_t;
typedef __kernel_off_t off_t;
typedef __kernel_loff_t loff_t;
#ifndef _PTRDIFF_T
#define _PTRDIFF_T
typedef __kernel_ptrdiff_t ptrdiff_t;
#endif
#ifndef _SIZE_T
#define _SIZE_T
typedef __kernel_size_t size_t;
#endif
#ifndef _SSIZE_T
#define _SSIZE_T
typedef __kernel_ssize_t ssize_t;
#endif
#ifndef __BIT_TYPES_DEFINED__
#define __BIT_TYPES_DEFINED__
typedef __u8 u_int8_t;
typedef __s8 int8_t;
typedef __u16 u_int16_t;
typedef __s16 int16_t;
typedef __u32 u_int32_t;
typedef __s32 int32_t;
#endif                          /* !(__BIT_TYPES_DEFINED__) */
typedef __u8 uint8_t;
typedef __u16 uint16_t;
typedef __u32 uint32_t;
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
typedef __u64 uint64_t;
typedef __u64 u_int64_t;
typedef __s64 int64_t;
#endif
#endif                          /* _LINUX_TYPES_H */
linux-bsp/asm-study/yaffs2/makefile
New file
@@ -0,0 +1,104 @@
# ***********************************************************************
# *        File:  makefile
# *     Version:  1.0.0
# *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
# * Description:  Makefile used to cross compile the ASM source code
# *   ChangeLog:  1, Release initial version on "Sun Mar 20 18:41:04 CST 2011"
# *
# ***********************************************************************
#
APP_NAME=bootstrap
INST_PATH=/tftp
SRC_TOP=$(CURDIR)
OBJS_MAIN := bootstrap.o start.o
OBJS_BSP += ${SRC_TOP}/bsp/*.o
OBJS_COMMON += ${SRC_TOP}/common/*.o
OBJS_YAFFS2 += ${SRC_TOP}/yaffs2/*.o
CFLAGS+=-I${SRC_TOP}/common
CFLAGS+=-I${SRC_TOP}/bsp
CFLAGS+=-I${SRC_TOP}/yaffs2
# Set the stack top base address here
TEXT_BASE=0x31000000
STACK_BASE=0x31010000
MALLOC_SIZE=0x100000
CFLAGS+=-DTEXT_BASE=$(TEXT_BASE) -DSTACK_BASE=${STACK_BASE} -DCONFIG_SYS_MALLOC_LEN=${MALLOC_SIZE}
CFLAGS+=-DDEBUG
gccincdir := $(shell $(CC) -print-file-name=include)
CFLAGS += -ffreestanding -nostdinc -isystem $(gccincdir) -pipe
CFLAGS+= -fno-strict-aliasing  -fno-common -ffixed-r8 -msoft-float
CFLAGS+=-march=armv4t -Wall -Wno-unused -Wstrict-prototypes -fno-stack-protector
CFLAGS += -fno-builtin
LDFLAGS=-Bstatic -T$(APP_NAME).lds -Ttext $(TEXT_BASE)
AFLAGS := $(CFLAGS) -D__ASSEMBLY__
export CFLAGS
export AFLAGS
#CFLAGS+=-Os -D__KERNEL__ -DCONFIG_ARM -D__ARM__
PLATFORM_LIBS += -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc
#PLATFORM_LIBS += -L/opt/buildroot-2011.11/arm920t/usr/arm-unknown-linux-uclibcgnueabi/sysroot/usr/lib/ -lc
CROSS_COMPILE=/opt/xtools/arm920t/bin/arm-linux-
AS  = $(CROSS_COMPILE)as
LD  = $(CROSS_COMPILE)ld
CC  = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR  = $(CROSS_COMPILE)ar
NM  = $(CROSS_COMPILE)nm
LDR = $(CROSS_COMPILE)ldr
STRIP   = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
RANLIB  = $(CROSS_COMPILE)RANLIB
export  CROSS_COMPILE AS LD CC CPP AR NM STRIP OBJCOPY OBJDUMP CFLAGS
ALL: clean bsp_lib common_lib yaffs2_lib ${OBJS_MAIN}
    echo ${OBJS_BSP}
    cd $(SRC_TOP)
    ${LD} $(LDFLAGS) \
    --start-group ${OBJS_BSP} ${OBJS_COMMON} ${OBJS_YAFFS2} $(OBJS_MAIN) \
    --end-group $(PLATFORM_LIBS) \
    -Map $(APP_NAME).map  -o $(APP_NAME).elf
    ${OBJCOPY} -O binary $(APP_NAME).elf $(APP_NAME).bin
    @chmod 777 $(APP_NAME).bin
    @rm -f *.elf *.o
    @make install
bsp_lib:
    @make -C bsp
common_lib:
    @make -C common
yaffs2_lib:
    @make -C yaffs2
%.o: %.S
     $(CC) $(AFLAGS) -c -o $@ $<
%.o: %.c
     $(CC) $(CFLAGS) -c -o $@ $<
install: $(APP_NAME).bin
    cp $(APP_NAME).bin $(INST_PATH) -f
clean:
    @find $(OBJTREE) -type f \
            \( -name 'core' -o -name '*.bak' -o -name '*~' -o -name .depend \
            -o -name '*.o'  -o -name '*.a' -o -name '*.elf' \) -print \
            | xargs rm -f
    @rm -f $(APP_NAME).bin
    @rm -f $(APP_NAME).map
    @make clean -C yaffs2
distclean clear: clean
    @rm -f cscope.* tags
linux-bsp/asm-study/yaffs2/start.S
New file
@@ -0,0 +1,60 @@
/********************************************************************************************
 *        File:  start.S - Startup Code for ARM920 CPU-core
 *     Version:  1.0.0
 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>
 * Description:  When system power up, the CPU will comes here to excute the first code here.
 *   ChangeLog:  1, Release initial version on "Tue Jul 12 16:43:18 CST 2011"
 *
 *******************************************************************************************/
/*
 *************************************************************************
 *
 * Jump vector table as in table 3.1 in [1]
 *
 *************************************************************************
 */
.globl _start
_start:    b    start_code
_TEXT_BASE:
    .word   TEXT_BASE
.globl _armboot_start
_armboot_start:
    .word _start
/*
 * These are defined in the board-specific linker script.
 */
.globl _bss_start
_bss_start:
    .word __bss_start
.globl _bss_end
_bss_end:
    .word _end
start_code:
    /* Set up the stack    */
stack_setup:
    ldr    r0, =TEXT_BASE        /* upper 128 KiB: relocated uboot   */
    sub    r0, r0, #CONFIG_SYS_MALLOC_LEN    /* malloc area              */
    sub    sp, r0, #12        /* leave 3 words for abort-stack    */
    bic    sp, sp, #7        /* 8-byte alignment for ABI compliance */
clear_bss:
    ldr    r0, _bss_start        /* find start of bss segment        */
    ldr    r1, _bss_end        /* stop here                        */
    mov    r2, #0x00000000        /* clear                            */
clbss_l:str    r2, [r0]        /* clear loop...                    */
    add    r0, r0, #4
    cmp    r0, r1
    ble    clbss_l
    bl  bootstrap_main
linux-bsp/asm-study/yaffs2/yaffs2/makefile
New file
@@ -0,0 +1,97 @@
#*********************************************************************************
#      Copyright:  (C) 2012 CoherentPlus Sdn. Bhd.
#                  All rights reserved.
#
#       Filename:  Makefile
#    Description:  This is the common subdir Makefile which to compile all the C
#                  source code to object files and then generate the shared or
#                  static library named lib$(FOLDER_NAME).a orlib $(FOLDER_NAME).so,
#                  which depends on the variable $LINK_MODE.
#
#        Version:  1.0.0(10/08/2011~)
#                  Author:  Guo Wenxue <guowenxue@gmail.com>
#      ChangeLog:  1, Release initial version on "10/08/2011 01:29:33 AM"
#
#********************************************************************************/
PWD=$(shell pwd)
LOCAL_COMPILE=YES
LINK_MODE=STATIC
#If wanna compile in the subdir, not called by top makefile, uncomment it
ifneq (${TOP_COMPILE}, YES)
LOCAL_COMPILE=YES
endif
LIBNAME=$(shell basename ${PWD})
STALIB=lib${LIBNAME}.a
DYNLIB=lib${LIBNAME}.so
VPATH= .
SRCS = $(wildcard ${VPATH}/*.c)
OBJS = $(patsubst %.c,%.o,$(SRCS))
#======================================================
#  ---> Doesn't call by top makefile, compile by local
#======================================================
ifeq (${LOCAL_COMPILE}, YES)
ARCH?=arm920t
#ARCH?=i386
CFLAGS+=-fPIC
TMP=$(shell echo $(ARCH) | tr "[A-Z]" "[a-z]")
ifneq (,$(filter i386,$(TMP)))
    CROSS_COMPILE=
else
    CROSS_COMPILE=/opt/xtools/arm920t/bin/arm-linux-
endif
PRJDIR?=$(shell pwd)
CFLAGS+=-I${PRJDIR}
CC = ${CROSS_COMPILE}gcc
AR = ${CROSS_COMPILE}ar
endif #End local compile
ifeq ("${LINK_MODE}", "STATIC")
    LIBS = ${STALIB}
else
    LIBS=${DYNLIB}
endif
all: entry ${LIBS} install
entry:
    @echo " ";
    @echo " =========================================================";
    @echo " **     Compile subdir ${LIBNAME} for ${ARCH}             ";
    @echo " =========================================================";
#$(LD) -g --relocatable $(OBJS) -o lib${LIBNAME}.o
${STALIB}:    $(OBJS)
    $(AR) -rcu $@ $(OBJS)
${DYNLIB}:   $(OBJS)
    $(CC) -fPIC -shared -o $@ $(OBJS)
%.o : %.c
    $(CC) -c $< $(CFLAGS)
tag:
    @ctags --c-kinds=+defglmnstuvx --langmap=c:.c.h.ho.hem.het.hec.hev.him.hit.hic.hiv -R .
    @cscope -Rbq
install:
    @if [ ! -z "${LIBS_PATH}" ] ; then \
        mkdir -p ${LIBS_PATH} ; \
        cp ${LIBS} ${LIBS_PATH}; \
    fi;
clean:
    @rm -f *.o
    @rm -rf *.gdb *.a *.so
distclean: clean
    @rm -f  tags cscope*
.PHONY: clean entry
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_allocator.c
New file
@@ -0,0 +1,357 @@
/*
 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
 *
 * Copyright (C) 2002-2011 Aleph One Ltd.
 *   for Toby Churchill Ltd and Brightstar Engineering
 *
 * Created by Charles Manning <charles@aleph1.co.uk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include "yaffs_allocator.h"
#include "yaffs_guts.h"
#include "yaffs_trace.h"
#include "yportenv.h"
/*
 * Each entry in yaffs_tnode_list and yaffs_obj_list hold blocks
 * of approx 100 objects that are themn allocated singly.
 * This is basically a simplified slab allocator.
 *
 * We don't use the Linux slab allocator because slab does not allow
 * us to dump all the objects in one hit when we do a umount and tear
 * down  all the tnodes and objects. slab requires that we first free
 * the individual objects.
 *
 * Once yaffs has been mainlined I shall try to motivate for a change
 * to slab to provide the extra features we need here.
 */
struct yaffs_tnode_list {
    struct yaffs_tnode_list *next;
    struct yaffs_tnode *tnodes;
};
struct yaffs_obj_list {
    struct yaffs_obj_list *next;
    struct yaffs_obj *objects;
};
struct yaffs_allocator {
    int n_tnodes_created;
    struct yaffs_tnode *free_tnodes;
    int n_free_tnodes;
    struct yaffs_tnode_list *alloc_tnode_list;
    int n_obj_created;
    struct list_head free_objs;
    int n_free_objects;
    struct yaffs_obj_list *allocated_obj_list;
};
static void yaffs_deinit_raw_tnodes(struct yaffs_dev *dev)
{
    struct yaffs_allocator *allocator =
        (struct yaffs_allocator *)dev->allocator;
    struct yaffs_tnode_list *tmp;
    if (!allocator) {
        BUG();
        return;
    }
    while (allocator->alloc_tnode_list) {
        tmp = allocator->alloc_tnode_list->next;
        kfree(allocator->alloc_tnode_list->tnodes);
        kfree(allocator->alloc_tnode_list);
        allocator->alloc_tnode_list = tmp;
    }
    allocator->free_tnodes = NULL;
    allocator->n_free_tnodes = 0;
    allocator->n_tnodes_created = 0;
}
static void yaffs_init_raw_tnodes(struct yaffs_dev *dev)
{
    struct yaffs_allocator *allocator = dev->allocator;
    if (!allocator) {
        BUG();
        return;
    }
    allocator->alloc_tnode_list = NULL;
    allocator->free_tnodes = NULL;
    allocator->n_free_tnodes = 0;
    allocator->n_tnodes_created = 0;
}
static int yaffs_create_tnodes(struct yaffs_dev *dev, int n_tnodes)
{
    struct yaffs_allocator *allocator =
        (struct yaffs_allocator *)dev->allocator;
    int i;
    struct yaffs_tnode *new_tnodes;
    u8 *mem;
    struct yaffs_tnode *curr;
    struct yaffs_tnode *next;
    struct yaffs_tnode_list *tnl;
    if (!allocator) {
        BUG();
        return YAFFS_FAIL;
    }
    if (n_tnodes < 1)
        return YAFFS_OK;
    /* make these things */
    new_tnodes = kmalloc(n_tnodes * dev->tnode_size, GFP_NOFS);
    mem = (u8 *) new_tnodes;
    if (!new_tnodes) {
        yaffs_trace(YAFFS_TRACE_ERROR,
            "yaffs: Could not allocate Tnodes");
        return YAFFS_FAIL;
    }
    /* New hookup for wide tnodes */
    for (i = 0; i < n_tnodes - 1; i++) {
        curr = (struct yaffs_tnode *)&mem[i * dev->tnode_size];
        next = (struct yaffs_tnode *)&mem[(i + 1) * dev->tnode_size];
        curr->internal[0] = next;
    }
    curr = (struct yaffs_tnode *)&mem[(n_tnodes - 1) * dev->tnode_size];
    curr->internal[0] = allocator->free_tnodes;
    allocator->free_tnodes = (struct yaffs_tnode *)mem;
    allocator->n_free_tnodes += n_tnodes;
    allocator->n_tnodes_created += n_tnodes;
    /* Now add this bunch of tnodes to a list for freeing up.
     * NB If we can't add this to the management list it isn't fatal
     * but it just means we can't free this bunch of tnodes later.
     */
    tnl = kmalloc(sizeof(struct yaffs_tnode_list), GFP_NOFS);
    if (!tnl) {
        yaffs_trace(YAFFS_TRACE_ERROR,
            "Could not add tnodes to management list");
        return YAFFS_FAIL;
    } else {
        tnl->tnodes = new_tnodes;
        tnl->next = allocator->alloc_tnode_list;
        allocator->alloc_tnode_list = tnl;
    }
    yaffs_trace(YAFFS_TRACE_ALLOCATE, "Tnodes added");
    return YAFFS_OK;
}
struct yaffs_tnode *yaffs_alloc_raw_tnode(struct yaffs_dev *dev)
{
    struct yaffs_allocator *allocator =
        (struct yaffs_allocator *)dev->allocator;
    struct yaffs_tnode *tn = NULL;
    if (!allocator) {
        BUG();
        return NULL;
    }
    /* If there are none left make more */
    if (!allocator->free_tnodes)
        yaffs_create_tnodes(dev, YAFFS_ALLOCATION_NTNODES);
    if (allocator->free_tnodes) {
        tn = allocator->free_tnodes;
        allocator->free_tnodes = allocator->free_tnodes->internal[0];
        allocator->n_free_tnodes--;
    }
    return tn;
}
/* FreeTnode frees up a tnode and puts it back on the free list */
void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn)
{
    struct yaffs_allocator *allocator = dev->allocator;
    if (!allocator) {
        BUG();
        return;
    }
    if (tn) {
        tn->internal[0] = allocator->free_tnodes;
        allocator->free_tnodes = tn;
        allocator->n_free_tnodes++;
    }
    dev->checkpoint_blocks_required = 0;    /* force recalculation */
}
/*--------------- yaffs_obj alloaction ------------------------
 *
 * Free yaffs_objs are stored in a list using obj->siblings.
 * The blocks of allocated objects are stored in a linked list.
 */
static void yaffs_init_raw_objs(struct yaffs_dev *dev)
{
    struct yaffs_allocator *allocator = dev->allocator;
    if (!allocator) {
        BUG();
        return;
    }
    allocator->allocated_obj_list = NULL;
    INIT_LIST_HEAD(&allocator->free_objs);
    allocator->n_free_objects = 0;
}
static void yaffs_deinit_raw_objs(struct yaffs_dev *dev)
{
    struct yaffs_allocator *allocator = dev->allocator;
    struct yaffs_obj_list *tmp;
    if (!allocator) {
        BUG();
        return;
    }
    while (allocator->allocated_obj_list) {
        tmp = allocator->allocated_obj_list->next;
        kfree(allocator->allocated_obj_list->objects);
        kfree(allocator->allocated_obj_list);
        allocator->allocated_obj_list = tmp;
    }
    INIT_LIST_HEAD(&allocator->free_objs);
    allocator->n_free_objects = 0;
    allocator->n_obj_created = 0;
}
static int yaffs_create_free_objs(struct yaffs_dev *dev, int n_obj)
{
    struct yaffs_allocator *allocator = dev->allocator;
    int i;
    struct yaffs_obj *new_objs;
    struct yaffs_obj_list *list;
    if (!allocator) {
        BUG();
        return YAFFS_FAIL;
    }
    if (n_obj < 1)
        return YAFFS_OK;
    /* make these things */
    new_objs = kmalloc(n_obj * sizeof(struct yaffs_obj), GFP_NOFS);
    list = kmalloc(sizeof(struct yaffs_obj_list), GFP_NOFS);
    if (!new_objs || !list) {
        kfree(new_objs);
        new_objs = NULL;
        kfree(list);
        list = NULL;
        yaffs_trace(YAFFS_TRACE_ALLOCATE,
            "Could not allocate more objects");
        return YAFFS_FAIL;
    }
    /* Hook them into the free list */
    for (i = 0; i < n_obj; i++)
        list_add(&new_objs[i].siblings, &allocator->free_objs);
    allocator->n_free_objects += n_obj;
    allocator->n_obj_created += n_obj;
    /* Now add this bunch of Objects to a list for freeing up. */
    list->objects = new_objs;
    list->next = allocator->allocated_obj_list;
    allocator->allocated_obj_list = list;
    return YAFFS_OK;
}
struct yaffs_obj *yaffs_alloc_raw_obj(struct yaffs_dev *dev)
{
    struct yaffs_obj *obj = NULL;
    struct list_head *lh;
    struct yaffs_allocator *allocator = dev->allocator;
    if (!allocator) {
        BUG();
        return obj;
    }
    /* If there are none left make more */
    if (list_empty(&allocator->free_objs))
        yaffs_create_free_objs(dev, YAFFS_ALLOCATION_NOBJECTS);
    if (!list_empty(&allocator->free_objs)) {
        lh = allocator->free_objs.next;
        obj = list_entry(lh, struct yaffs_obj, siblings);
        list_del_init(lh);
        allocator->n_free_objects--;
    }
    return obj;
}
void yaffs_free_raw_obj(struct yaffs_dev *dev, struct yaffs_obj *obj)
{
    struct yaffs_allocator *allocator = dev->allocator;
    if (!allocator) {
        BUG();
        return;
    }
    /* Link into the free list. */
    list_add(&obj->siblings, &allocator->free_objs);
    allocator->n_free_objects++;
}
void yaffs_deinit_raw_tnodes_and_objs(struct yaffs_dev *dev)
{
    if (!dev->allocator) {
        BUG();
        return;
    }
    yaffs_deinit_raw_tnodes(dev);
    yaffs_deinit_raw_objs(dev);
    kfree(dev->allocator);
    dev->allocator = NULL;
}
void yaffs_init_raw_tnodes_and_objs(struct yaffs_dev *dev)
{
    struct yaffs_allocator *allocator;
    if (dev->allocator) {
        BUG();
        return;
    }
    allocator = kmalloc(sizeof(struct yaffs_allocator), GFP_NOFS);
    if (allocator) {
        dev->allocator = allocator;
        yaffs_init_raw_tnodes(dev);
        yaffs_init_raw_objs(dev);
    }
}
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_allocator.h
New file
@@ -0,0 +1,30 @@
/*
 * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
 *
 * Copyright (C) 2002-2011 Aleph One Ltd.
 *   for Toby Churchill Ltd and Brightstar Engineering
 *
 * Created by Charles Manning <charles@aleph1.co.uk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 2.1 as
 * published by the Free Software Foundation.
 *
 * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
 */
#ifndef __YAFFS_ALLOCATOR_H__
#define __YAFFS_ALLOCATOR_H__
#include "yaffs_guts.h"
void yaffs_init_raw_tnodes_and_objs(struct yaffs_dev *dev);
void yaffs_deinit_raw_tnodes_and_objs(struct yaffs_dev *dev);
struct yaffs_tnode *yaffs_alloc_raw_tnode(struct yaffs_dev *dev);
void yaffs_free_raw_tnode(struct yaffs_dev *dev, struct yaffs_tnode *tn);
struct yaffs_obj *yaffs_alloc_raw_obj(struct yaffs_dev *dev);
void yaffs_free_raw_obj(struct yaffs_dev *dev, struct yaffs_obj *obj);
#endif
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_attribs.c
New file
@@ -0,0 +1,124 @@
/*
 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
 *
 * Copyright (C) 2002-2011 Aleph One Ltd.
 *   for Toby Churchill Ltd and Brightstar Engineering
 *
 * Created by Charles Manning <charles@aleph1.co.uk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include "yaffs_guts.h"
#include "yaffs_attribs.h"
void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh)
{
    obj->yst_uid = oh->yst_uid;
    obj->yst_gid = oh->yst_gid;
    obj->yst_atime = oh->yst_atime;
    obj->yst_mtime = oh->yst_mtime;
    obj->yst_ctime = oh->yst_ctime;
    obj->yst_rdev = oh->yst_rdev;
}
void yaffs_load_attribs_oh(struct yaffs_obj_hdr *oh, struct yaffs_obj *obj)
{
    oh->yst_uid = obj->yst_uid;
    oh->yst_gid = obj->yst_gid;
    oh->yst_atime = obj->yst_atime;
    oh->yst_mtime = obj->yst_mtime;
    oh->yst_ctime = obj->yst_ctime;
    oh->yst_rdev = obj->yst_rdev;
}
void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c)
{
    obj->yst_mtime = Y_CURRENT_TIME;
    if (do_a)
        obj->yst_atime = obj->yst_mtime;
    if (do_c)
        obj->yst_ctime = obj->yst_mtime;
}
void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev)
{
    yaffs_load_current_time(obj, 1, 1);
    obj->yst_rdev = rdev;
    obj->yst_uid = uid;
    obj->yst_gid = gid;
}
static loff_t yaffs_get_file_size(struct yaffs_obj *obj)
{
    YCHAR *alias = NULL;
    obj = yaffs_get_equivalent_obj(obj);
    switch (obj->variant_type) {
    case YAFFS_OBJECT_TYPE_FILE:
        return obj->variant.file_variant.file_size;
    case YAFFS_OBJECT_TYPE_SYMLINK:
        alias = obj->variant.symlink_variant.alias;
        if (!alias)
            return 0;
        return strnlen(alias, YAFFS_MAX_ALIAS_LENGTH);
    default:
        return 0;
    }
}
int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr)
{
    unsigned int valid = attr->ia_valid;
    if (valid & ATTR_MODE)
        obj->yst_mode = attr->ia_mode;
    if (valid & ATTR_UID)
        obj->yst_uid = attr->ia_uid;
    if (valid & ATTR_GID)
        obj->yst_gid = attr->ia_gid;
    if (valid & ATTR_ATIME)
        obj->yst_atime = Y_TIME_CONVERT(attr->ia_atime);
    if (valid & ATTR_CTIME)
        obj->yst_ctime = Y_TIME_CONVERT(attr->ia_ctime);
    if (valid & ATTR_MTIME)
        obj->yst_mtime = Y_TIME_CONVERT(attr->ia_mtime);
    if (valid & ATTR_SIZE)
        yaffs_resize_file(obj, attr->ia_size);
    yaffs_update_oh(obj, NULL, 1, 0, 0, NULL);
    return YAFFS_OK;
}
int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr)
{
    unsigned int valid = 0;
    attr->ia_mode = obj->yst_mode;
    valid |= ATTR_MODE;
    attr->ia_uid = obj->yst_uid;
    valid |= ATTR_UID;
    attr->ia_gid = obj->yst_gid;
    valid |= ATTR_GID;
    Y_TIME_CONVERT(attr->ia_atime) = obj->yst_atime;
    valid |= ATTR_ATIME;
    Y_TIME_CONVERT(attr->ia_ctime) = obj->yst_ctime;
    valid |= ATTR_CTIME;
    Y_TIME_CONVERT(attr->ia_mtime) = obj->yst_mtime;
    valid |= ATTR_MTIME;
    attr->ia_size = yaffs_get_file_size(obj);
    valid |= ATTR_SIZE;
    attr->ia_valid = valid;
    return YAFFS_OK;
}
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_attribs.h
New file
@@ -0,0 +1,28 @@
/*
 * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
 *
 * Copyright (C) 2002-2011 Aleph One Ltd.
 *   for Toby Churchill Ltd and Brightstar Engineering
 *
 * Created by Charles Manning <charles@aleph1.co.uk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 2.1 as
 * published by the Free Software Foundation.
 *
 * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
 */
#ifndef __YAFFS_ATTRIBS_H__
#define __YAFFS_ATTRIBS_H__
#include "yaffs_guts.h"
void yaffs_load_attribs(struct yaffs_obj *obj, struct yaffs_obj_hdr *oh);
void yaffs_load_attribs_oh(struct yaffs_obj_hdr *oh, struct yaffs_obj *obj);
void yaffs_attribs_init(struct yaffs_obj *obj, u32 gid, u32 uid, u32 rdev);
void yaffs_load_current_time(struct yaffs_obj *obj, int do_a, int do_c);
int yaffs_set_attribs(struct yaffs_obj *obj, struct iattr *attr);
int yaffs_get_attribs(struct yaffs_obj *obj, struct iattr *attr);
#endif
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_bitmap.c
New file
@@ -0,0 +1,97 @@
/*
 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
 *
 * Copyright (C) 2002-2011 Aleph One Ltd.
 *   for Toby Churchill Ltd and Brightstar Engineering
 *
 * Created by Charles Manning <charles@aleph1.co.uk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include "yaffs_bitmap.h"
#include "yaffs_trace.h"
/*
 * Chunk bitmap manipulations
 */
static inline u8 *yaffs_block_bits(struct yaffs_dev *dev, int blk)
{
    if (blk < dev->internal_start_block || blk > dev->internal_end_block) {
        yaffs_trace(YAFFS_TRACE_ERROR,
            "BlockBits block %d is not valid",
            blk);
        BUG();
    }
    return dev->chunk_bits +
        (dev->chunk_bit_stride * (blk - dev->internal_start_block));
}
void yaffs_verify_chunk_bit_id(struct yaffs_dev *dev, int blk, int chunk)
{
    if (blk < dev->internal_start_block || blk > dev->internal_end_block ||
        chunk < 0 || chunk >= dev->param.chunks_per_block) {
        yaffs_trace(YAFFS_TRACE_ERROR,
            "Chunk Id (%d:%d) invalid",
            blk, chunk);
        BUG();
    }
}
void yaffs_clear_chunk_bits(struct yaffs_dev *dev, int blk)
{
    u8 *blk_bits = yaffs_block_bits(dev, blk);
    memset(blk_bits, 0, dev->chunk_bit_stride);
}
void yaffs_clear_chunk_bit(struct yaffs_dev *dev, int blk, int chunk)
{
    u8 *blk_bits = yaffs_block_bits(dev, blk);
    yaffs_verify_chunk_bit_id(dev, blk, chunk);
    blk_bits[chunk / 8] &= ~(1 << (chunk & 7));
}
void yaffs_set_chunk_bit(struct yaffs_dev *dev, int blk, int chunk)
{
    u8 *blk_bits = yaffs_block_bits(dev, blk);
    yaffs_verify_chunk_bit_id(dev, blk, chunk);
    blk_bits[chunk / 8] |= (1 << (chunk & 7));
}
int yaffs_check_chunk_bit(struct yaffs_dev *dev, int blk, int chunk)
{
    u8 *blk_bits = yaffs_block_bits(dev, blk);
    yaffs_verify_chunk_bit_id(dev, blk, chunk);
    return (blk_bits[chunk / 8] & (1 << (chunk & 7))) ? 1 : 0;
}
int yaffs_still_some_chunks(struct yaffs_dev *dev, int blk)
{
    u8 *blk_bits = yaffs_block_bits(dev, blk);
    int i;
    for (i = 0; i < dev->chunk_bit_stride; i++) {
        if (*blk_bits)
            return 1;
        blk_bits++;
    }
    return 0;
}
int yaffs_count_chunk_bits(struct yaffs_dev *dev, int blk)
{
    u8 *blk_bits = yaffs_block_bits(dev, blk);
    int i;
    int n = 0;
    for (i = 0; i < dev->chunk_bit_stride; i++, blk_bits++)
        n += hweight8(*blk_bits);
    return n;
}
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_bitmap.h
New file
@@ -0,0 +1,33 @@
/*
 * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
 *
 * Copyright (C) 2002-2011 Aleph One Ltd.
 *   for Toby Churchill Ltd and Brightstar Engineering
 *
 * Created by Charles Manning <charles@aleph1.co.uk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 2.1 as
 * published by the Free Software Foundation.
 *
 * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
 */
/*
 * Chunk bitmap manipulations
 */
#ifndef __YAFFS_BITMAP_H__
#define __YAFFS_BITMAP_H__
#include "yaffs_guts.h"
void yaffs_verify_chunk_bit_id(struct yaffs_dev *dev, int blk, int chunk);
void yaffs_clear_chunk_bits(struct yaffs_dev *dev, int blk);
void yaffs_clear_chunk_bit(struct yaffs_dev *dev, int blk, int chunk);
void yaffs_set_chunk_bit(struct yaffs_dev *dev, int blk, int chunk);
int yaffs_check_chunk_bit(struct yaffs_dev *dev, int blk, int chunk);
int yaffs_still_some_chunks(struct yaffs_dev *dev, int blk);
int yaffs_count_chunk_bits(struct yaffs_dev *dev, int blk);
#endif
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_checkptrw.c
New file
@@ -0,0 +1,473 @@
/*
 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
 *
 * Copyright (C) 2002-2011 Aleph One Ltd.
 *   for Toby Churchill Ltd and Brightstar Engineering
 *
 * Created by Charles Manning <charles@aleph1.co.uk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include "yaffs_checkptrw.h"
#include "yaffs_getblockinfo.h"
struct yaffs_checkpt_chunk_hdr {
    int version;
    int seq;
    u32 sum;
    u32 xor;
} ;
static int apply_chunk_offset(struct yaffs_dev *dev, int chunk)
{
    return chunk - dev->chunk_offset;
}
static int apply_block_offset(struct yaffs_dev *dev, int block)
{
    return block - dev->block_offset;
}
static void yaffs2_checkpt_init_chunk_hdr(struct yaffs_dev *dev)
{
    struct yaffs_checkpt_chunk_hdr hdr;
    hdr.version = YAFFS_CHECKPOINT_VERSION;
    hdr.seq = dev->checkpt_page_seq;
    hdr.sum = dev->checkpt_sum;
    hdr.xor = dev->checkpt_xor;
    dev->checkpt_byte_offs = sizeof(hdr);
    memcpy(dev->checkpt_buffer, &hdr, sizeof(hdr));
}
static int yaffs2_checkpt_check_chunk_hdr(struct yaffs_dev *dev)
{
    struct yaffs_checkpt_chunk_hdr hdr;
    memcpy(&hdr, dev->checkpt_buffer, sizeof(hdr));
    dev->checkpt_byte_offs = sizeof(hdr);
    return hdr.version == YAFFS_CHECKPOINT_VERSION &&
        hdr.seq == dev->checkpt_page_seq &&
        hdr.sum == dev->checkpt_sum &&
        hdr.xor == dev->checkpt_xor;
}
static int yaffs2_checkpt_space_ok(struct yaffs_dev *dev)
{
    int blocks_avail = dev->n_erased_blocks - dev->param.n_reserved_blocks;
    yaffs_trace(YAFFS_TRACE_CHECKPOINT,
        "checkpt blocks_avail = %d", blocks_avail);
    return (blocks_avail <= 0) ? 0 : 1;
}
static int yaffs_checkpt_erase(struct yaffs_dev *dev)
{
    int i;
    if (!dev->param.erase_fn)
        return 0;
    yaffs_trace(YAFFS_TRACE_CHECKPOINT,
        "checking blocks %d to %d",
        dev->internal_start_block, dev->internal_end_block);
    for (i = dev->internal_start_block; i <= dev->internal_end_block; i++) {
        struct yaffs_block_info *bi = yaffs_get_block_info(dev, i);
        int offset_i = apply_block_offset(dev, i);
        int result;
        if (bi->block_state == YAFFS_BLOCK_STATE_CHECKPOINT) {
            yaffs_trace(YAFFS_TRACE_CHECKPOINT,
            "erasing checkpt block %d", i);
            dev->n_erasures++;
            result = dev->param.erase_fn(dev, offset_i);
            if(result) {
                bi->block_state = YAFFS_BLOCK_STATE_EMPTY;
                dev->n_erased_blocks++;
                dev->n_free_chunks +=
                    dev->param.chunks_per_block;
            } else {
                dev->param.bad_block_fn(dev, offset_i);
                bi->block_state = YAFFS_BLOCK_STATE_DEAD;
            }
        }
    }
    dev->blocks_in_checkpt = 0;
    return 1;
}
static void yaffs2_checkpt_find_erased_block(struct yaffs_dev *dev)
{
    int i;
    int blocks_avail = dev->n_erased_blocks - dev->param.n_reserved_blocks;
    yaffs_trace(YAFFS_TRACE_CHECKPOINT,
        "allocating checkpt block: erased %d reserved %d avail %d next %d ",
        dev->n_erased_blocks, dev->param.n_reserved_blocks,
        blocks_avail, dev->checkpt_next_block);
    if (dev->checkpt_next_block >= 0 &&
        dev->checkpt_next_block <= dev->internal_end_block &&
        blocks_avail > 0) {
        for (i = dev->checkpt_next_block; i <= dev->internal_end_block;
             i++) {
            struct yaffs_block_info *bi;
            bi = yaffs_get_block_info(dev, i);
            if (bi->block_state == YAFFS_BLOCK_STATE_EMPTY) {
                dev->checkpt_next_block = i + 1;
                dev->checkpt_cur_block = i;
                yaffs_trace(YAFFS_TRACE_CHECKPOINT,
                    "allocating checkpt block %d", i);
                return;
            }
        }
    }
    yaffs_trace(YAFFS_TRACE_CHECKPOINT, "out of checkpt blocks");
    dev->checkpt_next_block = -1;
    dev->checkpt_cur_block = -1;
}
static void yaffs2_checkpt_find_block(struct yaffs_dev *dev)
{
    int i;
    struct yaffs_ext_tags tags;
    yaffs_trace(YAFFS_TRACE_CHECKPOINT,
        "find next checkpt block: start:  blocks %d next %d",
        dev->blocks_in_checkpt, dev->checkpt_next_block);
    if (dev->blocks_in_checkpt < dev->checkpt_max_blocks)
        for (i = dev->checkpt_next_block; i <= dev->internal_end_block;
             i++) {
            int chunk = i * dev->param.chunks_per_block;
            enum yaffs_block_state state;
            u32 seq;
            dev->param.read_chunk_tags_fn(dev,
                    apply_chunk_offset(dev, chunk),
                    NULL, &tags);
            yaffs_trace(YAFFS_TRACE_CHECKPOINT,
                "find next checkpt block: search: block %d state %d oid %d seq %d eccr %d",
                i, (int) state,
                tags.obj_id, tags.seq_number,
                tags.ecc_result);
            if (tags.seq_number != YAFFS_SEQUENCE_CHECKPOINT_DATA)
                continue;
            dev->param.query_block_fn(dev,
                        apply_block_offset(dev, i),
                        &state, &seq);
            if (state == YAFFS_BLOCK_STATE_DEAD)
                continue;
            /* Right kind of block */
            dev->checkpt_next_block = tags.obj_id;
            dev->checkpt_cur_block = i;
            dev->checkpt_block_list[dev->blocks_in_checkpt] = i;
            dev->blocks_in_checkpt++;
            yaffs_trace(YAFFS_TRACE_CHECKPOINT,
                "found checkpt block %d", i);
            return;
        }
    yaffs_trace(YAFFS_TRACE_CHECKPOINT, "found no more checkpt blocks");
    dev->checkpt_next_block = -1;
    dev->checkpt_cur_block = -1;
}
int yaffs2_checkpt_open(struct yaffs_dev *dev, int writing)
{
    int i;
    dev->checkpt_open_write = writing;
    /* Got the functions we need? */
    if (!dev->param.write_chunk_tags_fn ||
        !dev->param.read_chunk_tags_fn ||
        !dev->param.erase_fn || !dev->param.bad_block_fn)
        return 0;
    if (writing && !yaffs2_checkpt_space_ok(dev))
        return 0;
    if (!dev->checkpt_buffer)
        dev->checkpt_buffer =
            kmalloc(dev->param.total_bytes_per_chunk, GFP_NOFS);
    if (!dev->checkpt_buffer)
        return 0;
    dev->checkpt_page_seq = 0;
    dev->checkpt_byte_count = 0;
    dev->checkpt_sum = 0;
    dev->checkpt_xor = 0;
    dev->checkpt_cur_block = -1;
    dev->checkpt_cur_chunk = -1;
    dev->checkpt_next_block = dev->internal_start_block;
    if (writing) {
        memset(dev->checkpt_buffer, 0, dev->data_bytes_per_chunk);
        yaffs2_checkpt_init_chunk_hdr(dev);
        return yaffs_checkpt_erase(dev);
    }
    /* Opening for a read */
    /* Set to a value that will kick off a read */
    dev->checkpt_byte_offs = dev->data_bytes_per_chunk;
    /* A checkpoint block list of 1 checkpoint block per 16 block is
     * (hopefully) going to be way more than we need */
    dev->blocks_in_checkpt = 0;
    dev->checkpt_max_blocks =
        (dev->internal_end_block - dev->internal_start_block) / 16 + 2;
    dev->checkpt_block_list =
        kmalloc(sizeof(int) * dev->checkpt_max_blocks, GFP_NOFS);
    if (!dev->checkpt_block_list)
        return 0;
    for (i = 0; i < dev->checkpt_max_blocks; i++)
        dev->checkpt_block_list[i] = -1;
    return 1;
}
int yaffs2_get_checkpt_sum(struct yaffs_dev *dev, u32 * sum)
{
    u32 composite_sum;
    composite_sum = (dev->checkpt_sum << 8) | (dev->checkpt_xor & 0xff);
    *sum = composite_sum;
    return 1;
}
static int yaffs2_checkpt_flush_buffer(struct yaffs_dev *dev)
{
    int chunk;
    int offset_chunk;
    struct yaffs_ext_tags tags;
    if (dev->checkpt_cur_block < 0) {
        yaffs2_checkpt_find_erased_block(dev);
        dev->checkpt_cur_chunk = 0;
    }
    if (dev->checkpt_cur_block < 0)
        return 0;
    tags.is_deleted = 0;
    tags.obj_id = dev->checkpt_next_block;    /* Hint to next place to look */
    tags.chunk_id = dev->checkpt_page_seq + 1;
    tags.seq_number = YAFFS_SEQUENCE_CHECKPOINT_DATA;
    tags.n_bytes = dev->data_bytes_per_chunk;
    if (dev->checkpt_cur_chunk == 0) {
        /* First chunk we write for the block? Set block state to
           checkpoint */
        struct yaffs_block_info *bi =
            yaffs_get_block_info(dev, dev->checkpt_cur_block);
        bi->block_state = YAFFS_BLOCK_STATE_CHECKPOINT;
        dev->blocks_in_checkpt++;
    }
    chunk =
        dev->checkpt_cur_block * dev->param.chunks_per_block +
        dev->checkpt_cur_chunk;
    yaffs_trace(YAFFS_TRACE_CHECKPOINT,
        "checkpoint wite buffer nand %d(%d:%d) objid %d chId %d",
        chunk, dev->checkpt_cur_block, dev->checkpt_cur_chunk,
        tags.obj_id, tags.chunk_id);
    offset_chunk = apply_chunk_offset(dev, chunk);
    dev->n_page_writes++;
    dev->param.write_chunk_tags_fn(dev, offset_chunk,
                       dev->checkpt_buffer, &tags);
    dev->checkpt_page_seq++;
    dev->checkpt_cur_chunk++;
    if (dev->checkpt_cur_chunk >= dev->param.chunks_per_block) {
        dev->checkpt_cur_chunk = 0;
        dev->checkpt_cur_block = -1;
    }
    memset(dev->checkpt_buffer, 0, dev->data_bytes_per_chunk);
    yaffs2_checkpt_init_chunk_hdr(dev);
    return 1;
}
int yaffs2_checkpt_wr(struct yaffs_dev *dev, const void *data, int n_bytes)
{
    int i = 0;
    int ok = 1;
    u8 *data_bytes = (u8 *) data;
    if (!dev->checkpt_buffer)
        return 0;
    if (!dev->checkpt_open_write)
        return -1;
    while (i < n_bytes && ok) {
        dev->checkpt_buffer[dev->checkpt_byte_offs] = *data_bytes;
        dev->checkpt_sum += *data_bytes;
        dev->checkpt_xor ^= *data_bytes;
        dev->checkpt_byte_offs++;
        i++;
        data_bytes++;
        dev->checkpt_byte_count++;
        if (dev->checkpt_byte_offs < 0 ||
            dev->checkpt_byte_offs >= dev->data_bytes_per_chunk)
            ok = yaffs2_checkpt_flush_buffer(dev);
    }
    return i;
}
int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes)
{
    int i = 0;
    int ok = 1;
    struct yaffs_ext_tags tags;
    int chunk;
    int offset_chunk;
    u8 *data_bytes = (u8 *) data;
    if (!dev->checkpt_buffer)
        return 0;
    if (dev->checkpt_open_write)
        return -1;
    while (i < n_bytes && ok) {
        if (dev->checkpt_byte_offs < 0 ||
            dev->checkpt_byte_offs >= dev->data_bytes_per_chunk) {
            if (dev->checkpt_cur_block < 0) {
                yaffs2_checkpt_find_block(dev);
                dev->checkpt_cur_chunk = 0;
            }
            if (dev->checkpt_cur_block < 0) {
                ok = 0;
                break;
            }
            chunk = dev->checkpt_cur_block *
                dev->param.chunks_per_block +
                dev->checkpt_cur_chunk;
            offset_chunk = apply_chunk_offset(dev, chunk);
            dev->n_page_reads++;
            /* read in the next chunk */
            dev->param.read_chunk_tags_fn(dev,
                        offset_chunk,
                        dev->checkpt_buffer,
                        &tags);
            if (tags.chunk_id != (dev->checkpt_page_seq + 1) ||
                tags.ecc_result > YAFFS_ECC_RESULT_FIXED ||
                tags.seq_number != YAFFS_SEQUENCE_CHECKPOINT_DATA) {
                ok = 0;
                break;
            }
            if(!yaffs2_checkpt_check_chunk_hdr(dev)) {
                ok = 0;
                break;
            }
            dev->checkpt_page_seq++;
            dev->checkpt_cur_chunk++;
            if (dev->checkpt_cur_chunk >=
                    dev->param.chunks_per_block)
                dev->checkpt_cur_block = -1;
        }
        *data_bytes = dev->checkpt_buffer[dev->checkpt_byte_offs];
        dev->checkpt_sum += *data_bytes;
        dev->checkpt_xor ^= *data_bytes;
        dev->checkpt_byte_offs++;
        i++;
        data_bytes++;
        dev->checkpt_byte_count++;
    }
    return i;
}
int yaffs_checkpt_close(struct yaffs_dev *dev)
{
    int i;
    if (dev->checkpt_open_write) {
        if (dev->checkpt_byte_offs !=
            sizeof(sizeof(struct yaffs_checkpt_chunk_hdr)))
            yaffs2_checkpt_flush_buffer(dev);
    } else if (dev->checkpt_block_list) {
        for (i = 0;
             i < dev->blocks_in_checkpt &&
             dev->checkpt_block_list[i] >= 0; i++) {
            int blk = dev->checkpt_block_list[i];
            struct yaffs_block_info *bi = NULL;
            if (dev->internal_start_block <= blk &&
                blk <= dev->internal_end_block)
                bi = yaffs_get_block_info(dev, blk);
            if (bi && bi->block_state == YAFFS_BLOCK_STATE_EMPTY)
                bi->block_state = YAFFS_BLOCK_STATE_CHECKPOINT;
        }
        kfree(dev->checkpt_block_list);
        dev->checkpt_block_list = NULL;
    }
    dev->n_free_chunks -=
        dev->blocks_in_checkpt * dev->param.chunks_per_block;
    dev->n_erased_blocks -= dev->blocks_in_checkpt;
    yaffs_trace(YAFFS_TRACE_CHECKPOINT, "checkpoint byte count %d",
        dev->checkpt_byte_count);
    if (dev->checkpt_buffer) {
        /* free the buffer */
        kfree(dev->checkpt_buffer);
        dev->checkpt_buffer = NULL;
        return 1;
    } else {
        return 0;
    }
}
int yaffs2_checkpt_invalidate_stream(struct yaffs_dev *dev)
{
    /* Erase the checkpoint data */
    yaffs_trace(YAFFS_TRACE_CHECKPOINT,
        "checkpoint invalidate of %d blocks",
        dev->blocks_in_checkpt);
    return yaffs_checkpt_erase(dev);
}
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_checkptrw.h
New file
@@ -0,0 +1,33 @@
/*
 * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
 *
 * Copyright (C) 2002-2011 Aleph One Ltd.
 *   for Toby Churchill Ltd and Brightstar Engineering
 *
 * Created by Charles Manning <charles@aleph1.co.uk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 2.1 as
 * published by the Free Software Foundation.
 *
 * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
 */
#ifndef __YAFFS_CHECKPTRW_H__
#define __YAFFS_CHECKPTRW_H__
#include "yaffs_guts.h"
int yaffs2_checkpt_open(struct yaffs_dev *dev, int writing);
int yaffs2_checkpt_wr(struct yaffs_dev *dev, const void *data, int n_bytes);
int yaffs2_checkpt_rd(struct yaffs_dev *dev, void *data, int n_bytes);
int yaffs2_get_checkpt_sum(struct yaffs_dev *dev, u32 * sum);
int yaffs_checkpt_close(struct yaffs_dev *dev);
int yaffs2_checkpt_invalidate_stream(struct yaffs_dev *dev);
#endif
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_ecc.c
New file
@@ -0,0 +1,281 @@
/*
 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
 *
 * Copyright (C) 2002-2011 Aleph One Ltd.
 *   for Toby Churchill Ltd and Brightstar Engineering
 *
 * Created by Charles Manning <charles@aleph1.co.uk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
/*
 * This code implements the ECC algorithm used in SmartMedia.
 *
 * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.
 * The two unused bit are set to 1.
 * The ECC can correct single bit errors in a 256-byte page of data. Thus, two
 * such ECC blocks are used on a 512-byte NAND page.
 *
 */
#include "yportenv.h"
#include "yaffs_ecc.h"
/* Table generated by gen-ecc.c
 * Using a table means we do not have to calculate p1..p4 and p1'..p4'
 * for each byte of data. These are instead provided in a table in bits7..2.
 * Bit 0 of each entry indicates whether the entry has an odd or even parity,
 * and therefore this bytes influence on the line parity.
 */
static const unsigned char column_parity_table[] = {
    0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
    0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
    0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
    0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
    0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
    0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
    0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
    0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
    0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
    0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
    0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
    0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
    0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
    0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
    0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
    0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
    0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0,
    0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
    0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55,
    0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
    0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59,
    0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
    0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc,
    0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
    0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65,
    0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
    0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0,
    0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
    0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc,
    0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
    0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69,
    0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
};
/* Calculate the ECC for a 256-byte block of data */
void yaffs_ecc_calc(const unsigned char *data, unsigned char *ecc)
{
    unsigned int i;
    unsigned char col_parity = 0;
    unsigned char line_parity = 0;
    unsigned char line_parity_prime = 0;
    unsigned char t;
    unsigned char b;
    for (i = 0; i < 256; i++) {
        b = column_parity_table[*data++];
        col_parity ^= b;
        if (b & 0x01) {    /* odd number of bits in the byte */
            line_parity ^= i;
            line_parity_prime ^= ~i;
        }
    }
    ecc[2] = (~col_parity) | 0x03;
    t = 0;
    if (line_parity & 0x80)
        t |= 0x80;
    if (line_parity_prime & 0x80)
        t |= 0x40;
    if (line_parity & 0x40)
        t |= 0x20;
    if (line_parity_prime & 0x40)
        t |= 0x10;
    if (line_parity & 0x20)
        t |= 0x08;
    if (line_parity_prime & 0x20)
        t |= 0x04;
    if (line_parity & 0x10)
        t |= 0x02;
    if (line_parity_prime & 0x10)
        t |= 0x01;
    ecc[1] = ~t;
    t = 0;
    if (line_parity & 0x08)
        t |= 0x80;
    if (line_parity_prime & 0x08)
        t |= 0x40;
    if (line_parity & 0x04)
        t |= 0x20;
    if (line_parity_prime & 0x04)
        t |= 0x10;
    if (line_parity & 0x02)
        t |= 0x08;
    if (line_parity_prime & 0x02)
        t |= 0x04;
    if (line_parity & 0x01)
        t |= 0x02;
    if (line_parity_prime & 0x01)
        t |= 0x01;
    ecc[0] = ~t;
}
/* Correct the ECC on a 256 byte block of data */
int yaffs_ecc_correct(unsigned char *data, unsigned char *read_ecc,
              const unsigned char *test_ecc)
{
    unsigned char d0, d1, d2;    /* deltas */
    d0 = read_ecc[0] ^ test_ecc[0];
    d1 = read_ecc[1] ^ test_ecc[1];
    d2 = read_ecc[2] ^ test_ecc[2];
    if ((d0 | d1 | d2) == 0)
        return 0;    /* no error */
    if (((d0 ^ (d0 >> 1)) & 0x55) == 0x55 &&
        ((d1 ^ (d1 >> 1)) & 0x55) == 0x55 &&
        ((d2 ^ (d2 >> 1)) & 0x54) == 0x54) {
        /* Single bit (recoverable) error in data */
        unsigned byte;
        unsigned bit;
        bit = byte = 0;
        if (d1 & 0x80)
            byte |= 0x80;
        if (d1 & 0x20)
            byte |= 0x40;
        if (d1 & 0x08)
            byte |= 0x20;
        if (d1 & 0x02)
            byte |= 0x10;
        if (d0 & 0x80)
            byte |= 0x08;
        if (d0 & 0x20)
            byte |= 0x04;
        if (d0 & 0x08)
            byte |= 0x02;
        if (d0 & 0x02)
            byte |= 0x01;
        if (d2 & 0x80)
            bit |= 0x04;
        if (d2 & 0x20)
            bit |= 0x02;
        if (d2 & 0x08)
            bit |= 0x01;
        data[byte] ^= (1 << bit);
        return 1;    /* Corrected the error */
    }
    if ((hweight8(d0) + hweight8(d1) + hweight8(d2)) == 1) {
        /* Reccoverable error in ecc */
        read_ecc[0] = test_ecc[0];
        read_ecc[1] = test_ecc[1];
        read_ecc[2] = test_ecc[2];
        return 1;    /* Corrected the error */
    }
    /* Unrecoverable error */
    return -1;
}
/*
 * ECCxxxOther does ECC calcs on arbitrary n bytes of data
 */
void yaffs_ecc_calc_other(const unsigned char *data, unsigned n_bytes,
              struct yaffs_ecc_other *ecc_other)
{
    unsigned int i;
    unsigned char col_parity = 0;
    unsigned line_parity = 0;
    unsigned line_parity_prime = 0;
    unsigned char b;
    for (i = 0; i < n_bytes; i++) {
        b = column_parity_table[*data++];
        col_parity ^= b;
        if (b & 0x01) {
            /* odd number of bits in the byte */
            line_parity ^= i;
            line_parity_prime ^= ~i;
        }
    }
    ecc_other->col_parity = (col_parity >> 2) & 0x3f;
    ecc_other->line_parity = line_parity;
    ecc_other->line_parity_prime = line_parity_prime;
}
int yaffs_ecc_correct_other(unsigned char *data, unsigned n_bytes,
                struct yaffs_ecc_other *read_ecc,
                const struct yaffs_ecc_other *test_ecc)
{
    unsigned char delta_col;    /* column parity delta */
    unsigned delta_line;    /* line parity delta */
    unsigned delta_line_prime;    /* line parity delta */
    unsigned bit;
    delta_col = read_ecc->col_parity ^ test_ecc->col_parity;
    delta_line = read_ecc->line_parity ^ test_ecc->line_parity;
    delta_line_prime =
        read_ecc->line_parity_prime ^ test_ecc->line_parity_prime;
    if ((delta_col | delta_line | delta_line_prime) == 0)
        return 0;    /* no error */
    if (delta_line == ~delta_line_prime &&
        (((delta_col ^ (delta_col >> 1)) & 0x15) == 0x15)) {
        /* Single bit (recoverable) error in data */
        bit = 0;
        if (delta_col & 0x20)
            bit |= 0x04;
        if (delta_col & 0x08)
            bit |= 0x02;
        if (delta_col & 0x02)
            bit |= 0x01;
        if (delta_line >= n_bytes)
            return -1;
        data[delta_line] ^= (1 << bit);
        return 1;    /* corrected */
    }
    if ((hweight32(delta_line) +
         hweight32(delta_line_prime) +
         hweight8(delta_col)) == 1) {
        /* Reccoverable error in ecc */
        *read_ecc = *test_ecc;
        return 1;    /* corrected */
    }
    /* Unrecoverable error */
    return -1;
}
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_ecc.h
New file
@@ -0,0 +1,44 @@
/*
 * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
 *
 * Copyright (C) 2002-2011 Aleph One Ltd.
 *   for Toby Churchill Ltd and Brightstar Engineering
 *
 * Created by Charles Manning <charles@aleph1.co.uk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 2.1 as
 * published by the Free Software Foundation.
 *
 * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
 */
/*
 * This code implements the ECC algorithm used in SmartMedia.
 *
 * The ECC comprises 22 bits of parity information and is stuffed into 3 bytes.
 * The two unused bit are set to 1.
 * The ECC can correct single bit errors in a 256-byte page of data.
 * Thus, two such ECC blocks are used on a 512-byte NAND page.
 *
 */
#ifndef __YAFFS_ECC_H__
#define __YAFFS_ECC_H__
struct yaffs_ecc_other {
    unsigned char col_parity;
    unsigned line_parity;
    unsigned line_parity_prime;
};
void yaffs_ecc_calc(const unsigned char *data, unsigned char *ecc);
int yaffs_ecc_correct(unsigned char *data, unsigned char *read_ecc,
              const unsigned char *test_ecc);
void yaffs_ecc_calc_other(const unsigned char *data, unsigned n_bytes,
              struct yaffs_ecc_other *ecc);
int yaffs_ecc_correct_other(unsigned char *data, unsigned n_bytes,
                struct yaffs_ecc_other *read_ecc,
                const struct yaffs_ecc_other *test_ecc);
#endif
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_error.c
New file
@@ -0,0 +1,58 @@
/*
 * YAFFS: Yet another FFS. A NAND-flash specific file system.
 *
 * Copyright (C) 2002-2011 Aleph One Ltd.
 *   for Toby Churchill Ltd and Brightstar Engineering
 *
 * Created by Timothy Manning <timothy@yaffs.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include "yaffsfs.h"
struct error_entry {
    int code;
    const char *text;
};
static const struct error_entry error_list[] = {
    { ENOMEM , "ENOMEM" },
    { EBUSY , "EBUSY"},
    { ENODEV , "ENODEV"},
    { EINVAL , "EINVAL"},
    { EBADF , "EBADF"},
    { EACCES , "EACCES"},
    { EXDEV , "EXDEV" },
    { ENOENT , "ENOENT"},
    { ENOSPC , "ENOSPC"},
    { ERANGE , "ERANGE"},
    { ENODATA, "ENODATA"},
    { ENOTEMPTY, "ENOTEMPTY"},
    { ENAMETOOLONG, "ENAMETOOLONG"},
    { ENOMEM , "ENOMEM"},
    { EEXIST , "EEXIST"},
    { ENOTDIR , "ENOTDIR"},
    { EISDIR , "EISDIR"},
    { ENFILE, "ENFILE"},
    { EROFS, "EROFS"},
    { EFAULT, "EFAULT"},
    { 0, NULL }
};
const char *yaffs_error_to_str(int err)
{
    const struct error_entry *e = error_list;
    if (err < 0)
        err = -err;
    while (e->code && e->text) {
        if (err == e->code)
            return e->text;
        e++;
    }
    return "Unknown error code";
}
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_flashif.h
New file
@@ -0,0 +1,35 @@
/*
 * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
 *
 * Copyright (C) 2002-2011 Aleph One Ltd.
 *   for Toby Churchill Ltd and Brightstar Engineering
 *
 * Created by Charles Manning <charles@aleph1.co.uk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 2.1 as
 * published by the Free Software Foundation.
 *
 * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
 */
#ifndef __YAFFS_FLASH_H__
#define __YAFFS_FLASH_H__
#include "yaffs_guts.h"
int yflash_EraseBlockInNAND(struct yaffs_dev *dev, int blockNumber);
int yflash_WriteChunkToNAND(struct yaffs_dev *dev, int nand_chunk,
            const u8 *data, const struct yaffs_spare *spare);
int yflash_WriteChunkWithTagsToNAND(struct yaffs_dev *dev, int nand_chunk,
            const u8 *data, const struct yaffs_ext_tags *tags);
int yflash_ReadChunkFromNAND(struct yaffs_dev *dev, int nand_chunk,
            u8 *data, struct yaffs_spare *spare);
int yflash_ReadChunkWithTagsFromNAND(struct yaffs_dev *dev, int nand_chunk,
            u8 *data, struct yaffs_ext_tags *tags);
int yflash_InitialiseNAND(struct yaffs_dev *dev);
int yflash_MarkNANDBlockBad(struct yaffs_dev *dev, int block_no);
int yflash_QueryNANDBlock(struct yaffs_dev *dev, int block_no,
            enum yaffs_block_state *state, u32 *seq_number);
#endif
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_flashif2.h
New file
@@ -0,0 +1,35 @@
/*
 * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
 *
 * Copyright (C) 2002-2011 Aleph One Ltd.
 *   for Toby Churchill Ltd and Brightstar Engineering
 *
 * Created by Charles Manning <charles@aleph1.co.uk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 2.1 as
 * published by the Free Software Foundation.
 *
 * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
 */
#ifndef __YAFFS_FLASH2_H__
#define __YAFFS_FLASH2_H__
#include "yaffs_guts.h"
int yflash2_EraseBlockInNAND(struct yaffs_dev *dev, int blockNumber);
int yflash2_WriteChunkToNAND(struct yaffs_dev *dev, int nand_chunk,
            const u8 *data, const struct yaffs_spare *spare);
int yflash2_WriteChunkWithTagsToNAND(struct yaffs_dev *dev, int nand_chunk,
            const u8 *data, const struct yaffs_ext_tags *tags);
int yflash2_ReadChunkFromNAND(struct yaffs_dev *dev, int nand_chunk,
            u8 *data, struct yaffs_spare *spare);
int yflash2_ReadChunkWithTagsFromNAND(struct yaffs_dev *dev, int nand_chunk,
            u8 *data, struct yaffs_ext_tags *tags);
int yflash2_InitialiseNAND(struct yaffs_dev *dev);
int yflash2_MarkNANDBlockBad(struct yaffs_dev *dev, int block_no);
int yflash2_QueryNANDBlock(struct yaffs_dev *dev, int block_no,
            enum yaffs_block_state *state, u32 *seq_number);
#endif
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_getblockinfo.h
New file
@@ -0,0 +1,35 @@
/*
 * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
 *
 * Copyright (C) 2002-2011 Aleph One Ltd.
 *   for Toby Churchill Ltd and Brightstar Engineering
 *
 * Created by Charles Manning <charles@aleph1.co.uk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 2.1 as
 * published by the Free Software Foundation.
 *
 * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
 */
#ifndef __YAFFS_GETBLOCKINFO_H__
#define __YAFFS_GETBLOCKINFO_H__
#include "yaffs_guts.h"
#include "yaffs_trace.h"
/* Function to manipulate block info */
static inline struct yaffs_block_info *yaffs_get_block_info(struct yaffs_dev
                                  *dev, int blk)
{
    if (blk < dev->internal_start_block || blk > dev->internal_end_block) {
        yaffs_trace(YAFFS_TRACE_ERROR,
            "**>> yaffs: get_block_info block %d is not valid",
            blk);
        BUG();
    }
    return &dev->block_info[blk - dev->internal_start_block];
}
#endif
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_guts.c
New file
Diff too large
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_guts.h
New file
@@ -0,0 +1,977 @@
/*
 * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
 *
 * Copyright (C) 2002-2011 Aleph One Ltd.
 *   for Toby Churchill Ltd and Brightstar Engineering
 *
 * Created by Charles Manning <charles@aleph1.co.uk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 2.1 as
 * published by the Free Software Foundation.
 *
 * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
 */
#ifndef __YAFFS_GUTS_H__
#define __YAFFS_GUTS_H__
#include "yportenv.h"
#define YAFFS_OK    1
#define YAFFS_FAIL  0
/* Give us a  Y=0x59,
 * Give us an A=0x41,
 * Give us an FF=0xff
 * Give us an S=0x53
 * And what have we got...
 */
#define YAFFS_MAGIC            0x5941ff53
/*
 * Tnodes form a tree with the tnodes in "levels"
 * Levels greater than 0 hold 8 slots which point to other tnodes.
 * Those at level 0 hold 16 slots which point to chunks in NAND.
 *
 * A maximum level of 8 thust supports files of size up to:
 *
 * 2^(3*MAX_LEVEL+4)
 *
 * Thus a max level of 8 supports files with up to 2^^28 chunks which gives
 * a maximum file size of arounf 51Gbytees with 2k chunks.
 */
#define YAFFS_NTNODES_LEVEL0        16
#define YAFFS_TNODES_LEVEL0_BITS    4
#define YAFFS_TNODES_LEVEL0_MASK    0xf
#define YAFFS_NTNODES_INTERNAL        (YAFFS_NTNODES_LEVEL0 / 2)
#define YAFFS_TNODES_INTERNAL_BITS    (YAFFS_TNODES_LEVEL0_BITS - 1)
#define YAFFS_TNODES_INTERNAL_MASK    0x7
#define YAFFS_TNODES_MAX_LEVEL        8
#define YAFFS_TNODES_MAX_BITS        (YAFFS_TNODES_LEVEL0_BITS + \
                    YAFFS_TNODES_INTERNAL_BITS * \
                    YAFFS_TNODES_MAX_LEVEL)
#define YAFFS_MAX_CHUNK_ID        ((1 << YAFFS_TNODES_MAX_BITS) - 1)
#define YAFFS_MAX_FILE_SIZE_32        0x7fffffff
/* Constants for YAFFS1 mode */
#define YAFFS_BYTES_PER_SPARE        16
#define YAFFS_BYTES_PER_CHUNK        512
#define YAFFS_CHUNK_SIZE_SHIFT        9
#define YAFFS_CHUNKS_PER_BLOCK        32
#define YAFFS_BYTES_PER_BLOCK    (YAFFS_CHUNKS_PER_BLOCK*YAFFS_BYTES_PER_CHUNK)
#define YAFFS_MIN_YAFFS2_CHUNK_SIZE    1024
#define YAFFS_MIN_YAFFS2_SPARE_SIZE    32
#define YAFFS_ALLOCATION_NOBJECTS    100
#define YAFFS_ALLOCATION_NTNODES    100
#define YAFFS_ALLOCATION_NLINKS        100
#define YAFFS_NOBJECT_BUCKETS        256
#define YAFFS_OBJECT_SPACE        0x40000
#define YAFFS_MAX_OBJECT_ID        (YAFFS_OBJECT_SPACE - 1)
/* Binary data version stamps */
#define YAFFS_SUMMARY_VERSION        1
#define YAFFS_CHECKPOINT_VERSION    7
#ifdef CONFIG_YAFFS_UNICODE
#define YAFFS_MAX_NAME_LENGTH        127
#define YAFFS_MAX_ALIAS_LENGTH        79
#else
#define YAFFS_MAX_NAME_LENGTH        255
#define YAFFS_MAX_ALIAS_LENGTH        159
#endif
#define YAFFS_SHORT_NAME_LENGTH        15
/* Some special object ids for pseudo objects */
#define YAFFS_OBJECTID_ROOT        1
#define YAFFS_OBJECTID_LOSTNFOUND    2
#define YAFFS_OBJECTID_UNLINKED        3
#define YAFFS_OBJECTID_DELETED        4
/* Fake object Id for summary data */
#define YAFFS_OBJECTID_SUMMARY        0x10
/* Pseudo object ids for checkpointing */
#define YAFFS_OBJECTID_CHECKPOINT_DATA    0x20
#define YAFFS_SEQUENCE_CHECKPOINT_DATA    0x21
#define YAFFS_MAX_SHORT_OP_CACHES    20
#define YAFFS_N_TEMP_BUFFERS        6
/* We limit the number attempts at sucessfully saving a chunk of data.
 * Small-page devices have 32 pages per block; large-page devices have 64.
 * Default to something in the order of 5 to 10 blocks worth of chunks.
 */
#define YAFFS_WR_ATTEMPTS        (5*64)
/* Sequence numbers are used in YAFFS2 to determine block allocation order.
 * The range is limited slightly to help distinguish bad numbers from good.
 * This also allows us to perhaps in the future use special numbers for
 * special purposes.
 * EFFFFF00 allows the allocation of 8 blocks/second (~1Mbytes) for 15 years,
 * and is a larger number than the lifetime of a 2GB device.
 */
#define YAFFS_LOWEST_SEQUENCE_NUMBER    0x00001000
#define YAFFS_HIGHEST_SEQUENCE_NUMBER    0xefffff00
/* Special sequence number for bad block that failed to be marked bad */
#define YAFFS_SEQUENCE_BAD_BLOCK    0xffff0000
/* ChunkCache is used for short read/write operations.*/
struct yaffs_cache {
    struct yaffs_obj *object;
    int chunk_id;
    int last_use;
    int dirty;
    int n_bytes;        /* Only valid if the cache is dirty */
    int locked;        /* Can't push out or flush while locked. */
    u8 *data;
};
/* yaffs1 tags structures in RAM
 * NB This uses bitfield. Bitfields should not straddle a u32 boundary
 * otherwise the structure size will get blown out.
 */
struct yaffs_tags {
    unsigned chunk_id:20;
    unsigned serial_number:2;
    unsigned n_bytes_lsb:10;
    unsigned obj_id:18;
    unsigned ecc:12;
    unsigned n_bytes_msb:2;
};
union yaffs_tags_union {
    struct yaffs_tags as_tags;
    u8 as_bytes[8];
};
/* Stuff used for extended tags in YAFFS2 */
enum yaffs_ecc_result {
    YAFFS_ECC_RESULT_UNKNOWN,
    YAFFS_ECC_RESULT_NO_ERROR,
    YAFFS_ECC_RESULT_FIXED,
    YAFFS_ECC_RESULT_UNFIXED
};
enum yaffs_obj_type {
    YAFFS_OBJECT_TYPE_UNKNOWN,
    YAFFS_OBJECT_TYPE_FILE,
    YAFFS_OBJECT_TYPE_SYMLINK,
    YAFFS_OBJECT_TYPE_DIRECTORY,
    YAFFS_OBJECT_TYPE_HARDLINK,
    YAFFS_OBJECT_TYPE_SPECIAL
};
#define YAFFS_OBJECT_TYPE_MAX YAFFS_OBJECT_TYPE_SPECIAL
struct yaffs_ext_tags {
    unsigned chunk_used;    /*  Status of the chunk: used or unused */
    unsigned obj_id;    /* If 0 this is not used */
    unsigned chunk_id;    /* If 0 this is a header, else a data chunk */
    unsigned n_bytes;    /* Only valid for data chunks */
    /* The following stuff only has meaning when we read */
    enum yaffs_ecc_result ecc_result;
    unsigned block_bad;
    /* YAFFS 1 stuff */
    unsigned is_deleted;    /* The chunk is marked deleted */
    unsigned serial_number;    /* Yaffs1 2-bit serial number */
    /* YAFFS2 stuff */
    unsigned seq_number;    /* The sequence number of this block */
    /* Extra info if this is an object header (YAFFS2 only) */
    unsigned extra_available;    /* Extra info available if not zero */
    unsigned extra_parent_id;    /* The parent object */
    unsigned extra_is_shrink;    /* Is it a shrink header? */
    unsigned extra_shadows;    /* Does this shadow another object? */
    enum yaffs_obj_type extra_obj_type;    /* What object type? */
    loff_t extra_file_size;        /* Length if it is a file */
    unsigned extra_equiv_id;    /* Equivalent object for a hard link */
};
/* Spare structure for YAFFS1 */
struct yaffs_spare {
    u8 tb0;
    u8 tb1;
    u8 tb2;
    u8 tb3;
    u8 page_status;        /* set to 0 to delete the chunk */
    u8 block_status;
    u8 tb4;
    u8 tb5;
    u8 ecc1[3];
    u8 tb6;
    u8 tb7;
    u8 ecc2[3];
};
/*Special structure for passing through to mtd */
struct yaffs_nand_spare {
    struct yaffs_spare spare;
    int eccres1;
    int eccres2;
};
/* Block data in RAM */
enum yaffs_block_state {
    YAFFS_BLOCK_STATE_UNKNOWN = 0,
    YAFFS_BLOCK_STATE_SCANNING,
    /* Being scanned */
    YAFFS_BLOCK_STATE_NEEDS_SCAN,
    /* The block might have something on it (ie it is allocating or full,
     * perhaps empty) but it needs to be scanned to determine its true
     * state.
     * This state is only valid during scanning.
     * NB We tolerate empty because the pre-scanner might be incapable of
     * deciding
     * However, if this state is returned on a YAFFS2 device,
     * then we expect a sequence number
     */
    YAFFS_BLOCK_STATE_EMPTY,
    /* This block is empty */
    YAFFS_BLOCK_STATE_ALLOCATING,
    /* This block is partially allocated.
     * At least one page holds valid data.
     * This is the one currently being used for page
     * allocation. Should never be more than one of these.
     * If a block is only partially allocated at mount it is treated as
     * full.
     */
    YAFFS_BLOCK_STATE_FULL,
    /* All the pages in this block have been allocated.
     * If a block was only partially allocated when mounted we treat
     * it as fully allocated.
     */
    YAFFS_BLOCK_STATE_DIRTY,
    /* The block was full and now all chunks have been deleted.
     * Erase me, reuse me.
     */
    YAFFS_BLOCK_STATE_CHECKPOINT,
    /* This block is assigned to holding checkpoint data. */
    YAFFS_BLOCK_STATE_COLLECTING,
    /* This block is being garbage collected */
    YAFFS_BLOCK_STATE_DEAD
        /* This block has failed and is not in use */
};
#define    YAFFS_NUMBER_OF_BLOCK_STATES (YAFFS_BLOCK_STATE_DEAD + 1)
struct yaffs_block_info {
    int soft_del_pages:10;    /* number of soft deleted pages */
    int pages_in_use:10;    /* number of pages in use */
    unsigned block_state:4;    /* One of the above block states. */
                /* NB use unsigned because enum is sometimes
                 * an int */
    u32 needs_retiring:1;    /* Data has failed on this block, */
                /*need to get valid data off and retire*/
    u32 skip_erased_check:1;/* Skip the erased check on this block */
    u32 gc_prioritise:1;    /* An ECC check or blank check has failed.
                   Block should be prioritised for GC */
    u32 chunk_error_strikes:3;    /* How many times we've had ecc etc
                failures on this block and tried to reuse it */
    u32 has_summary:1;    /* The block has a summary */
    u32 has_shrink_hdr:1;    /* This block has at least one shrink header */
    u32 seq_number;        /* block sequence number for yaffs2 */
};
/* -------------------------- Object structure -------------------------------*/
/* This is the object structure as stored on NAND */
struct yaffs_obj_hdr {
    enum yaffs_obj_type type;
    /* Apply to everything  */
    int parent_obj_id;
    u16 sum_no_longer_used;    /* checksum of name. No longer used */
    YCHAR name[YAFFS_MAX_NAME_LENGTH + 1];
    /* The following apply to all object types except for hard links */
    u32 yst_mode;        /* protection */
    u32 yst_uid;
    u32 yst_gid;
    u32 yst_atime;
    u32 yst_mtime;
    u32 yst_ctime;
    /* File size  applies to files only */
    u32 file_size_low;
    /* Equivalent object id applies to hard links only. */
    int equiv_id;
    /* Alias is for symlinks only. */
    YCHAR alias[YAFFS_MAX_ALIAS_LENGTH + 1];
    u32 yst_rdev;    /* stuff for block and char devices (major/min) */
    u32 win_ctime[2];
    u32 win_atime[2];
    u32 win_mtime[2];
    u32 inband_shadowed_obj_id;
    u32 inband_is_shrink;
    u32 file_size_high;
    u32 reserved[1];
    int shadows_obj;    /* This object header shadows the
                specified object if > 0 */
    /* is_shrink applies to object headers written when wemake a hole. */
    u32 is_shrink;
};
/*--------------------------- Tnode -------------------------- */
struct yaffs_tnode {
    struct yaffs_tnode *internal[YAFFS_NTNODES_INTERNAL];
};
/*------------------------  Object -----------------------------*/
/* An object can be one of:
 * - a directory (no data, has children links
 * - a regular file (data.... not prunes :->).
 * - a symlink [symbolic link] (the alias).
 * - a hard link
 */
struct yaffs_file_var {
    loff_t file_size;
    loff_t scanned_size;
    loff_t shrink_size;
    int top_level;
    struct yaffs_tnode *top;
};
struct yaffs_dir_var {
    struct list_head children;    /* list of child links */
    struct list_head dirty;    /* Entry for list of dirty directories */
};
struct yaffs_symlink_var {
    YCHAR *alias;
};
struct yaffs_hardlink_var {
    struct yaffs_obj *equiv_obj;
    u32 equiv_id;
};
union yaffs_obj_var {
    struct yaffs_file_var file_variant;
    struct yaffs_dir_var dir_variant;
    struct yaffs_symlink_var symlink_variant;
    struct yaffs_hardlink_var hardlink_variant;
};
struct yaffs_obj {
    u8 deleted:1;        /* This should only apply to unlinked files. */
    u8 soft_del:1;        /* it has also been soft deleted */
    u8 unlinked:1;        /* An unlinked file.*/
    u8 fake:1;        /* A fake object has no presence on NAND. */
    u8 rename_allowed:1;    /* Some objects cannot be renamed. */
    u8 unlink_allowed:1;
    u8 dirty:1;        /* the object needs to be written to flash */
    u8 valid:1;        /* When the file system is being loaded up, this
                 * object might be created before the data
                 * is available
                 * ie. file data chunks encountered before
                * the header.
                 */
    u8 lazy_loaded:1;    /* This object has been lazy loaded and
                 * is missing some detail */
    u8 defered_free:1;    /* Object is removed from NAND, but is
                 * still in the inode cache.
                 * Free of object is defered.
                 * until the inode is released.
                 */
    u8 being_created:1;    /* This object is still being created
                 * so skip some verification checks. */
    u8 is_shadowed:1;    /* This object is shadowed on the way
                 * to being renamed. */
    u8 xattr_known:1;    /* We know if this has object has xattribs
                 * or not. */
    u8 has_xattr:1;        /* This object has xattribs.
                 * Only valid if xattr_known. */
    u8 serial;        /* serial number of chunk in NAND.*/
    u16 sum;        /* sum of the name to speed searching */
    struct yaffs_dev *my_dev;    /* The device I'm on */
    struct list_head hash_link;    /* list of objects in hash bucket */
    struct list_head hard_links;    /* hard linked object chain*/
    /* directory structure stuff */
    /* also used for linking up the free list */
    struct yaffs_obj *parent;
    struct list_head siblings;
    /* Where's my object header in NAND? */
    int hdr_chunk;
    int n_data_chunks;    /* Number of data chunks for this file. */
    u32 obj_id;        /* the object id value */
    u32 yst_mode;
    YCHAR short_name[YAFFS_SHORT_NAME_LENGTH + 1];
#ifdef CONFIG_YAFFS_WINCE
    u32 win_ctime[2];
    u32 win_mtime[2];
    u32 win_atime[2];
#else
    u32 yst_uid;
    u32 yst_gid;
    u32 yst_atime;
    u32 yst_mtime;
    u32 yst_ctime;
#endif
    u32 yst_rdev;
    void *my_inode;
    enum yaffs_obj_type variant_type;
    union yaffs_obj_var variant;
};
struct yaffs_obj_bucket {
    struct list_head list;
    int count;
};
/* yaffs_checkpt_obj holds the definition of an object as dumped
 * by checkpointing.
 */
struct yaffs_checkpt_obj {
    int struct_type;
    u32 obj_id;
    u32 parent_id;
    int hdr_chunk;
    enum yaffs_obj_type variant_type:3;
    u8 deleted:1;
    u8 soft_del:1;
    u8 unlinked:1;
    u8 fake:1;
    u8 rename_allowed:1;
    u8 unlink_allowed:1;
    u8 serial;
    int n_data_chunks;
    loff_t size_or_equiv_obj;
};
/*--------------------- Temporary buffers ----------------
 *
 * These are chunk-sized working buffers. Each device has a few.
 */
struct yaffs_buffer {
    u8 *buffer;
    int in_use;
};
/*----------------- Device ---------------------------------*/
struct yaffs_param {
    const YCHAR *name;
    /*
     * Entry parameters set up way early. Yaffs sets up the rest.
     * The structure should be zeroed out before use so that unused
     * and defualt values are zero.
     */
    int inband_tags;    /* Use unband tags */
    u32 total_bytes_per_chunk;    /* Should be >= 512, does not need to
                     be a power of 2 */
    int chunks_per_block;    /* does not need to be a power of 2 */
    int spare_bytes_per_chunk;    /* spare area size */
    int start_block;    /* Start block we're allowed to use */
    int end_block;        /* End block we're allowed to use */
    int n_reserved_blocks;    /* Tuneable so that we can reduce
                 * reserved blocks on NOR and RAM. */
    int n_caches;        /* If <= 0, then short op caching is disabled,
                 * else the number of short op caches.
                 */
    int use_nand_ecc;    /* Flag to decide whether or not to use
                 * NAND driver ECC on data (yaffs1) */
    int tags_9bytes;    /* Use 9 byte tags */
    int no_tags_ecc;    /* Flag to decide whether or not to do ECC
                 * on packed tags (yaffs2) */
    int is_yaffs2;        /* Use yaffs2 mode on this device */
    int empty_lost_n_found;    /* Auto-empty lost+found directory on mount */
    int refresh_period;    /* How often to check for a block refresh */
    /* Checkpoint control. Can be set before or after initialisation */
    u8 skip_checkpt_rd;
    u8 skip_checkpt_wr;
    int enable_xattr;    /* Enable xattribs */
    /* NAND access functions (Must be set before calling YAFFS) */
    int (*write_chunk_fn) (struct yaffs_dev *dev,
                   int nand_chunk, const u8 *data,
                   const struct yaffs_spare *spare);
    int (*read_chunk_fn) (struct yaffs_dev *dev,
                  int nand_chunk, u8 *data,
                  struct yaffs_spare *spare);
    int (*erase_fn) (struct yaffs_dev *dev, int flash_block);
    int (*initialise_flash_fn) (struct yaffs_dev *dev);
    int (*deinitialise_flash_fn) (struct yaffs_dev *dev);
    /* yaffs2 mode functions */
    int (*write_chunk_tags_fn) (struct yaffs_dev *dev,
                    int nand_chunk, const u8 *data,
                    const struct yaffs_ext_tags *tags);
    int (*read_chunk_tags_fn) (struct yaffs_dev *dev,
                   int nand_chunk, u8 *data,
                   struct yaffs_ext_tags *tags);
    int (*bad_block_fn) (struct yaffs_dev *dev, int block_no);
    int (*query_block_fn) (struct yaffs_dev *dev, int block_no,
                   enum yaffs_block_state *state,
                   u32 *seq_number);
    /* The remove_obj_fn function must be supplied by OS flavours that
     * need it.
     * yaffs direct uses it to implement the faster readdir.
     * Linux uses it to protect the directory during unlocking.
     */
    void (*remove_obj_fn) (struct yaffs_obj *obj);
    /* Callback to mark the superblock dirty */
    void (*sb_dirty_fn) (struct yaffs_dev *dev);
    /*  Callback to control garbage collection. */
    unsigned (*gc_control) (struct yaffs_dev *dev);
    /* Debug control flags. Don't use unless you know what you're doing */
    int use_header_file_size;    /* Flag to determine if we should use
                     * file sizes from the header */
    int disable_lazy_load;    /* Disable lazy loading on this device */
    int wide_tnodes_disabled;    /* Set to disable wide tnodes */
    int disable_soft_del;    /* yaffs 1 only: Set to disable the use of
                 * softdeletion. */
    int defered_dir_update;    /* Set to defer directory updates */
#ifdef CONFIG_YAFFS_AUTO_UNICODE
    int auto_unicode;
#endif
    int always_check_erased;    /* Force chunk erased check always on */
    int disable_summary;
    int max_objects;    /*
                 * Set to limit the number of objects created.
                 * 0 = no limit.
                */
};
struct yaffs_dev {
    struct yaffs_param param;
    /* Context storage. Holds extra OS specific data for this device */
    void *os_context;
    void *driver_context;
    struct list_head dev_list;
    /* Runtime parameters. Set up by YAFFS. */
    int data_bytes_per_chunk;
    /* Non-wide tnode stuff */
    u16 chunk_grp_bits;    /* Number of bits that need to be resolved if
                 * the tnodes are not wide enough.
                 */
    u16 chunk_grp_size;    /* == 2^^chunk_grp_bits */
    /* Stuff to support wide tnodes */
    u32 tnode_width;
    u32 tnode_mask;
    u32 tnode_size;
    /* Stuff for figuring out file offset to chunk conversions */
    u32 chunk_shift;    /* Shift value */
    u32 chunk_div;        /* Divisor after shifting: 1 for 2^n sizes */
    u32 chunk_mask;        /* Mask to use for power-of-2 case */
    int is_mounted;
    int read_only;
    int is_checkpointed;
    /* Stuff to support block offsetting to support start block zero */
    int internal_start_block;
    int internal_end_block;
    int block_offset;
    int chunk_offset;
    /* Runtime checkpointing stuff */
    int checkpt_page_seq;    /* running sequence number of checkpt pages */
    int checkpt_byte_count;
    int checkpt_byte_offs;
    u8 *checkpt_buffer;
    int checkpt_open_write;
    int blocks_in_checkpt;
    int checkpt_cur_chunk;
    int checkpt_cur_block;
    int checkpt_next_block;
    int *checkpt_block_list;
    int checkpt_max_blocks;
    u32 checkpt_sum;
    u32 checkpt_xor;
    int checkpoint_blocks_required;    /* Number of blocks needed to store
                     * current checkpoint set */
    /* Block Info */
    struct yaffs_block_info *block_info;
    u8 *chunk_bits;        /* bitmap of chunks in use */
    unsigned block_info_alt:1;    /* allocated using alternative alloc */
    unsigned chunk_bits_alt:1;    /* allocated using alternative alloc */
    int chunk_bit_stride;    /* Number of bytes of chunk_bits per block.
                 * Must be consistent with chunks_per_block.
                 */
    int n_erased_blocks;
    int alloc_block;    /* Current block being allocated off */
    u32 alloc_page;
    int alloc_block_finder;    /* Used to search for next allocation block */
    /* Object and Tnode memory management */
    void *allocator;
    int n_obj;
    int n_tnodes;
    int n_hardlinks;
    struct yaffs_obj_bucket obj_bucket[YAFFS_NOBJECT_BUCKETS];
    u32 bucket_finder;
    int n_free_chunks;
    /* Garbage collection control */
    u32 *gc_cleanup_list;    /* objects to delete at the end of a GC. */
    u32 n_clean_ups;
    unsigned has_pending_prioritised_gc;    /* We think this device might
                        have pending prioritised gcs */
    unsigned gc_disable;
    unsigned gc_block_finder;
    unsigned gc_dirtiest;
    unsigned gc_pages_in_use;
    unsigned gc_not_done;
    unsigned gc_block;
    unsigned gc_chunk;
    unsigned gc_skip;
    struct yaffs_summary_tags *gc_sum_tags;
    /* Special directories */
    struct yaffs_obj *root_dir;
    struct yaffs_obj *lost_n_found;
    int buffered_block;    /* Which block is buffered here? */
    int doing_buffered_block_rewrite;
    struct yaffs_cache *cache;
    int cache_last_use;
    /* Stuff for background deletion and unlinked files. */
    struct yaffs_obj *unlinked_dir;    /* Directory where unlinked and deleted
                     files live. */
    struct yaffs_obj *del_dir;    /* Directory where deleted objects are
                    sent to disappear. */
    struct yaffs_obj *unlinked_deletion;    /* Current file being
                            background deleted. */
    int n_deleted_files;    /* Count of files awaiting deletion; */
    int n_unlinked_files;    /* Count of unlinked files. */
    int n_bg_deletions;    /* Count of background deletions. */
    /* Temporary buffer management */
    struct yaffs_buffer temp_buffer[YAFFS_N_TEMP_BUFFERS];
    int max_temp;
    int temp_in_use;
    int unmanaged_buffer_allocs;
    int unmanaged_buffer_deallocs;
    /* yaffs2 runtime stuff */
    unsigned seq_number;    /* Sequence number of currently
                    allocating block */
    unsigned oldest_dirty_seq;
    unsigned oldest_dirty_block;
    /* Block refreshing */
    int refresh_skip;    /* A skip down counter.
                 * Refresh happens when this gets to zero. */
    /* Dirty directory handling */
    struct list_head dirty_dirs;    /* List of dirty directories */
    /* Summary */
    int chunks_per_summary;
    struct yaffs_summary_tags *sum_tags;
    /* Statistics */
    u32 n_page_writes;
    u32 n_page_reads;
    u32 n_erasures;
    u32 n_erase_failures;
    u32 n_gc_copies;
    u32 all_gcs;
    u32 passive_gc_count;
    u32 oldest_dirty_gc_count;
    u32 n_gc_blocks;
    u32 bg_gcs;
    u32 n_retried_writes;
    u32 n_retired_blocks;
    u32 n_ecc_fixed;
    u32 n_ecc_unfixed;
    u32 n_tags_ecc_fixed;
    u32 n_tags_ecc_unfixed;
    u32 n_deletions;
    u32 n_unmarked_deletions;
    u32 refresh_count;
    u32 cache_hits;
    u32 tags_used;
    u32 summary_used;
};
/* The CheckpointDevice structure holds the device information that changes
 *at runtime and must be preserved over unmount/mount cycles.
 */
struct yaffs_checkpt_dev {
    int struct_type;
    int n_erased_blocks;
    int alloc_block;    /* Current block being allocated off */
    u32 alloc_page;
    int n_free_chunks;
    int n_deleted_files;    /* Count of files awaiting deletion; */
    int n_unlinked_files;    /* Count of unlinked files. */
    int n_bg_deletions;    /* Count of background deletions. */
    /* yaffs2 runtime stuff */
    unsigned seq_number;    /* Sequence number of currently
                 * allocating block */
};
struct yaffs_checkpt_validity {
    int struct_type;
    u32 magic;
    u32 version;
    u32 head;
};
struct yaffs_shadow_fixer {
    int obj_id;
    int shadowed_id;
    struct yaffs_shadow_fixer *next;
};
/* Structure for doing xattr modifications */
struct yaffs_xattr_mod {
    int set;        /* If 0 then this is a deletion */
    const YCHAR *name;
    const void *data;
    int size;
    int flags;
    int result;
};
/*----------------------- YAFFS Functions -----------------------*/
int yaffs_guts_initialise(struct yaffs_dev *dev);
void yaffs_deinitialise(struct yaffs_dev *dev);
int yaffs_get_n_free_chunks(struct yaffs_dev *dev);
int yaffs_rename_obj(struct yaffs_obj *old_dir, const YCHAR * old_name,
             struct yaffs_obj *new_dir, const YCHAR * new_name);
int yaffs_unlinker(struct yaffs_obj *dir, const YCHAR * name);
int yaffs_del_obj(struct yaffs_obj *obj);
int yaffs_get_obj_name(struct yaffs_obj *obj, YCHAR * name, int buffer_size);
loff_t yaffs_get_obj_length(struct yaffs_obj *obj);
int yaffs_get_obj_inode(struct yaffs_obj *obj);
unsigned yaffs_get_obj_type(struct yaffs_obj *obj);
int yaffs_get_obj_link_count(struct yaffs_obj *obj);
/* File operations */
int yaffs_file_rd(struct yaffs_obj *obj, u8 * buffer, loff_t offset,
          int n_bytes);
int yaffs_wr_file(struct yaffs_obj *obj, const u8 * buffer, loff_t offset,
          int n_bytes, int write_trhrough);
int yaffs_resize_file(struct yaffs_obj *obj, loff_t new_size);
struct yaffs_obj *yaffs_create_file(struct yaffs_obj *parent,
                    const YCHAR *name, u32 mode, u32 uid,
                    u32 gid);
int yaffs_flush_file(struct yaffs_obj *obj, int update_time, int data_sync);
/* Flushing and checkpointing */
void yaffs_flush_whole_cache(struct yaffs_dev *dev);
int yaffs_checkpoint_save(struct yaffs_dev *dev);
int yaffs_checkpoint_restore(struct yaffs_dev *dev);
/* Directory operations */
struct yaffs_obj *yaffs_create_dir(struct yaffs_obj *parent, const YCHAR *name,
                   u32 mode, u32 uid, u32 gid);
struct yaffs_obj *yaffs_find_by_name(struct yaffs_obj *the_dir,
                     const YCHAR *name);
struct yaffs_obj *yaffs_find_by_number(struct yaffs_dev *dev, u32 number);
/* Link operations */
struct yaffs_obj *yaffs_link_obj(struct yaffs_obj *parent, const YCHAR *name,
                 struct yaffs_obj *equiv_obj);
struct yaffs_obj *yaffs_get_equivalent_obj(struct yaffs_obj *obj);
/* Symlink operations */
struct yaffs_obj *yaffs_create_symlink(struct yaffs_obj *parent,
                       const YCHAR *name, u32 mode, u32 uid,
                       u32 gid, const YCHAR *alias);
YCHAR *yaffs_get_symlink_alias(struct yaffs_obj *obj);
/* Special inodes (fifos, sockets and devices) */
struct yaffs_obj *yaffs_create_special(struct yaffs_obj *parent,
                       const YCHAR *name, u32 mode, u32 uid,
                       u32 gid, u32 rdev);
int yaffs_set_xattrib(struct yaffs_obj *obj, const YCHAR *name,
              const void *value, int size, int flags);
int yaffs_get_xattrib(struct yaffs_obj *obj, const YCHAR *name, void *value,
              int size);
int yaffs_list_xattrib(struct yaffs_obj *obj, char *buffer, int size);
int yaffs_remove_xattrib(struct yaffs_obj *obj, const YCHAR *name);
/* Special directories */
struct yaffs_obj *yaffs_root(struct yaffs_dev *dev);
struct yaffs_obj *yaffs_lost_n_found(struct yaffs_dev *dev);
void yaffs_handle_defered_free(struct yaffs_obj *obj);
void yaffs_update_dirty_dirs(struct yaffs_dev *dev);
int yaffs_bg_gc(struct yaffs_dev *dev, unsigned urgency);
/* Debug dump  */
int yaffs_dump_obj(struct yaffs_obj *obj);
void yaffs_guts_test(struct yaffs_dev *dev);
/* A few useful functions to be used within the core files*/
void yaffs_chunk_del(struct yaffs_dev *dev, int chunk_id, int mark_flash,
             int lyn);
int yaffs_check_ff(u8 *buffer, int n_bytes);
void yaffs_handle_chunk_error(struct yaffs_dev *dev,
                  struct yaffs_block_info *bi);
u8 *yaffs_get_temp_buffer(struct yaffs_dev *dev);
void yaffs_release_temp_buffer(struct yaffs_dev *dev, u8 *buffer);
struct yaffs_obj *yaffs_find_or_create_by_number(struct yaffs_dev *dev,
                         int number,
                         enum yaffs_obj_type type);
int yaffs_put_chunk_in_file(struct yaffs_obj *in, int inode_chunk,
                int nand_chunk, int in_scan);
void yaffs_set_obj_name(struct yaffs_obj *obj, const YCHAR *name);
void yaffs_set_obj_name_from_oh(struct yaffs_obj *obj,
                const struct yaffs_obj_hdr *oh);
void yaffs_add_obj_to_dir(struct yaffs_obj *directory, struct yaffs_obj *obj);
YCHAR *yaffs_clone_str(const YCHAR *str);
void yaffs_link_fixup(struct yaffs_dev *dev, struct list_head *hard_list);
void yaffs_block_became_dirty(struct yaffs_dev *dev, int block_no);
int yaffs_update_oh(struct yaffs_obj *in, const YCHAR *name,
            int force, int is_shrink, int shadows,
            struct yaffs_xattr_mod *xop);
void yaffs_handle_shadowed_obj(struct yaffs_dev *dev, int obj_id,
                   int backward_scanning);
int yaffs_check_alloc_available(struct yaffs_dev *dev, int n_chunks);
struct yaffs_tnode *yaffs_get_tnode(struct yaffs_dev *dev);
struct yaffs_tnode *yaffs_add_find_tnode_0(struct yaffs_dev *dev,
                       struct yaffs_file_var *file_struct,
                       u32 chunk_id,
                       struct yaffs_tnode *passed_tn);
int yaffs_do_file_wr(struct yaffs_obj *in, const u8 *buffer, loff_t offset,
             int n_bytes, int write_trhrough);
void yaffs_resize_file_down(struct yaffs_obj *obj, loff_t new_size);
void yaffs_skip_rest_of_block(struct yaffs_dev *dev);
int yaffs_count_free_chunks(struct yaffs_dev *dev);
struct yaffs_tnode *yaffs_find_tnode_0(struct yaffs_dev *dev,
                       struct yaffs_file_var *file_struct,
                       u32 chunk_id);
u32 yaffs_get_group_base(struct yaffs_dev *dev, struct yaffs_tnode *tn,
             unsigned pos);
int yaffs_is_non_empty_dir(struct yaffs_obj *obj);
int yaffs_format_dev(struct yaffs_dev *dev);
void yaffs_addr_to_chunk(struct yaffs_dev *dev, loff_t addr,
                int *chunk_out, u32 *offset_out);
/*
 * Marshalling functions to get loff_t file sizes into aand out of
 * object headers.
 */
void yaffs_oh_size_load(struct yaffs_obj_hdr *oh, loff_t fsize);
loff_t yaffs_oh_to_size(struct yaffs_obj_hdr *oh);
loff_t yaffs_max_file_size(struct yaffs_dev *dev);
#endif
Diff truncated after the above file
linux-bsp/asm-study/yaffs2/yaffs2/yaffs_hweight.c linux-bsp/asm-study/yaffs2/yaffs2/yaffs_hweight.h linux-bsp/asm-study/yaffs2/yaffs2/yaffs_k9f2g08.c linux-bsp/asm-study/yaffs2/yaffs2/yaffs_k9f2g08.h linux-bsp/asm-study/yaffs2/yaffs2/yaffs_list.h linux-bsp/asm-study/yaffs2/yaffs2/yaffs_nameval.c linux-bsp/asm-study/yaffs2/yaffs2/yaffs_nameval.h linux-bsp/asm-study/yaffs2/yaffs2/yaffs_nand.c linux-bsp/asm-study/yaffs2/yaffs2/yaffs_nand.h linux-bsp/asm-study/yaffs2/yaffs2/yaffs_osglue.c linux-bsp/asm-study/yaffs2/yaffs2/yaffs_osglue.h linux-bsp/asm-study/yaffs2/yaffs2/yaffs_packedtags2.c linux-bsp/asm-study/yaffs2/yaffs2/yaffs_packedtags2.h linux-bsp/asm-study/yaffs2/yaffs2/yaffs_qsort.c linux-bsp/asm-study/yaffs2/yaffs2/yaffs_summary.c linux-bsp/asm-study/yaffs2/yaffs2/yaffs_summary.h linux-bsp/asm-study/yaffs2/yaffs2/yaffs_tagscompat.c linux-bsp/asm-study/yaffs2/yaffs2/yaffs_tagscompat.h linux-bsp/asm-study/yaffs2/yaffs2/yaffs_trace.h linux-bsp/asm-study/yaffs2/yaffs2/yaffs_verify.c linux-bsp/asm-study/yaffs2/yaffs2/yaffs_verify.h linux-bsp/asm-study/yaffs2/yaffs2/yaffs_yaffs1.c linux-bsp/asm-study/yaffs2/yaffs2/yaffs_yaffs1.h linux-bsp/asm-study/yaffs2/yaffs2/yaffs_yaffs2.c linux-bsp/asm-study/yaffs2/yaffs2/yaffs_yaffs2.h linux-bsp/asm-study/yaffs2/yaffs2/yaffscfg.h linux-bsp/asm-study/yaffs2/yaffs2/yaffscfg2k.c linux-bsp/asm-study/yaffs2/yaffs2/yaffsfs.c linux-bsp/asm-study/yaffs2/yaffs2/yaffsfs.h linux-bsp/asm-study/yaffs2/yaffs2/ydirectenv.h linux-bsp/asm-study/yaffs2/yaffs2/yportenv.h linux-bsp/bootstrap/bootstrap.S linux-bsp/bootstrap/bootstrap.h linux-bsp/bootstrap/build.sh linux-bsp/bootstrap/makefile linux-bsp/build.sh linux-bsp/driver/Makefile linux-bsp/driver/kernel_hello.c linux-bsp/driver/platdev_led.c linux-bsp/driver/platdev_led.h linux-bsp/driver/platdrv_key.c linux-bsp/driver/platdrv_led.c linux-bsp/driver/s3c_led.c linux-bsp/driver/test/makefile linux-bsp/driver/test/test_plat_key.c linux-bsp/driver/test/test_plat_led.c linux-bsp/driver/test/test_s3c_led.c linux-bsp/driver/x86/Makefile linux-bsp/driver/x86/kernel_hello.c linux-bsp/patches/gen_patch.sh linux-bsp/patches/linux-3.0-fl2440.patch linux-bsp/patches/u-boot-2010.09-fl2440.patch linux-bsp/patches/u-boot-serial-patch/u-boot-2010.09-1-basic.patch linux-bsp/patches/u-boot-serial-patch/u-boot-2010.09-2-dm9000.patch linux-bsp/patches/u-boot-serial-patch/u-boot-2010.09-3-nand.patch linux-bsp/patches/u-boot-serial-patch/u-boot-2010.09-4-linux.patch linux-bsp/tarballs/rootfs.tar.bz2