Index: embios/branches/4g_compat/Makefile |
— | — | @@ -0,0 +1,66 @@ |
| 2 | +NAME := embios
|
| 3 | +TARGETS := ipodnano2g ipodnano4g
|
| 4 | +
|
| 5 | +CROSS := arm-none-eabi-
|
| 6 | +CC := $(CROSS)gcc
|
| 7 | +AS := $(CROSS)as
|
| 8 | +LD := $(CROSS)ld
|
| 9 | +OBJCOPY := $(CROSS)objcopy
|
| 10 | +UCLPACK := ucl2e10singleblk
|
| 11 | +
|
| 12 | +CFLAGS ?= -Os -fno-pie -fno-stack-protector -fomit-frame-pointer -I. -ffunction-sections -fdata-sections -std=gnu99
|
| 13 | +LDFLAGS ?= "$(shell $(CC) -print-libgcc-file-name)" --gc-sections
|
| 14 | +
|
| 15 | +preprocess = $(shell $(CC) $(PPCFLAGS) $(2) -E -P -x c $(1) | grep -v "^\#" | sed -e "s:^..*:$(dir $(1))&:")
|
| 16 | +
|
| 17 | +define TARGET_template
|
| 18 | +SRC_$(1) := $$(call preprocess,SOURCES,-DTARGET_$(1))
|
| 19 | +OBJ_$(1) := $$(SRC_$(1):%.c=build/$(1)/%.o)
|
| 20 | +OBJ_$(1) := $$(OBJ_$(1):%.S=build/$(1)/%.o)
|
| 21 | +
|
| 22 | +-include $$(OBJ_$(1):%=%.dep)
|
| 23 | +
|
| 24 | +$(1): build/$(1)/$(NAME)-$(1).ucl
|
| 25 | +
|
| 26 | +build/$(1)/$(NAME)-$(1).ucl: build/$(1)/$(NAME).bin
|
| 27 | + $(UCLPACK) $$^ $$@
|
| 28 | +
|
| 29 | +build/$(1)/$(NAME).bin: build/$(1)/$(NAME).elf
|
| 30 | + $(OBJCOPY) -O binary $$^ $$@
|
| 31 | +
|
| 32 | +build/$(1)/$(NAME).elf: target/$(1)/ls.x build/$(1)/target/$(1)/crt0.o $$(OBJ_$(1))
|
| 33 | + $(LD) $(LDFLAGS) -o $$@ -T target/$(1)/ls.x $$(OBJ_$(1))
|
| 34 | +
|
| 35 | +build/$(1)/%.o: %.c
|
| 36 | +ifeq ($(shell uname),WindowsNT)
|
| 37 | + @-if not exist $$(subst /,\,$$(dir $$@)) md $$(subst /,\,$$(dir $$@))
|
| 38 | +else
|
| 39 | + @-mkdir -p $$(dir $$@)
|
| 40 | +endif
|
| 41 | + $(CC) -c $(CFLAGS) -Itarget/$(1) -DTARGET_$(1) -o $$@ $$<
|
| 42 | + @$(CC) -MM $(CFLAGS) -Itarget/$(1) -DTARGET_$(1) $$< > $$@.dep.tmp
|
| 43 | + @sed -e "s|.*:|$$@:|" < $$@.dep.tmp > $$@.dep
|
| 44 | + @sed -e "s/.*://" -e "s/\\$$$$//" < $$@.dep.tmp | fmt -1 | sed -e "s/^ *//" -e "s/$$$$/:/" >> $$@.dep
|
| 45 | + @rm -f $$@.dep.tmp
|
| 46 | +
|
| 47 | +build/$(1)/%.o: %.S
|
| 48 | +ifeq ($(shell uname),WindowsNT)
|
| 49 | + @-if not exist $$(subst /,\,$$(dir $$@)) md $$(subst /,\,$$(dir $$@))
|
| 50 | +else
|
| 51 | + @-mkdir -p $$(dir $$@)
|
| 52 | +endif
|
| 53 | + $(CC) -c $(CFLAGS) -Itarget/$(1) -DTARGET_$(1) -o $$@ $$<
|
| 54 | + @$(CC) -MM $(CFLAGS) -Itarget/$(1) -DTARGET_$(1) $$< > $$@.dep.tmp
|
| 55 | + @sed -e "s|.*:|$$@:|" < $$@.dep.tmp > $$@.dep
|
| 56 | + @sed -e "s/.*://" -e "s/\\$$$$//" < $$@.dep.tmp | fmt -1 | sed -e "s/^ *//" -e "s/$$$$/:/" >> $$@.dep
|
| 57 | + @rm -f $$@.dep.tmp
|
| 58 | +endef
|
| 59 | +
|
| 60 | +all: $(TARGETS)
|
| 61 | +
|
| 62 | +$(foreach target,$(TARGETS),$(eval $(call TARGET_template,$(target))))
|
| 63 | +
|
| 64 | +clean:
|
| 65 | + rm -rf build
|
| 66 | +
|
| 67 | +.PHONY: all clean $(TARGETS)
|
Index: embios/branches/4g_compat/SOURCES |
— | — | @@ -0,0 +1,28 @@ |
| 2 | +#ifdef TARGET_ipodnano2g
|
| 3 | +target/ipodnano2g/mmu.c
|
| 4 | +target/ipodnano2g/lcd.c
|
| 5 | +target/ipodnano2g/nand.c
|
| 6 | +target/ipodnano2g/storage.c
|
| 7 | +target/ipodnano2g/i2c.S
|
| 8 | +#endif
|
| 9 | +
|
| 10 | +#ifdef TARGET_ipodnano4g
|
| 11 | +target/ipodnano4g/mmu.c
|
| 12 | +target/ipodnano4g/lcd.c
|
| 13 | +target/ipodnano4g/storage.c
|
| 14 | +#endif
|
| 15 | +
|
| 16 | +init.c
|
| 17 | +main.c
|
| 18 | +util.c
|
| 19 | +drawing.S
|
| 20 | +lcdconsole.c
|
| 21 | +format.c
|
| 22 | +snprintf.c
|
| 23 | +panic.c
|
| 24 | +console.c
|
| 25 | +arm-support.S
|
| 26 | +strlen.c
|
| 27 | +fat32.c
|
| 28 | +ucl.S
|
| 29 | +
|
Index: embios/branches/4g_compat/target/ipodnano4g/mmu.c |
— | — | @@ -0,0 +1,34 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#include "global.h"
|
| 26 | +#include "mmu.h"
|
| 27 | +
|
| 28 | +
|
| 29 | +void clean_dcache()
|
| 30 | +{
|
| 31 | +}
|
| 32 | +
|
| 33 | +void invalidate_dcache()
|
| 34 | +{
|
| 35 | +}
|
Index: embios/branches/4g_compat/target/ipodnano4g/lcd.S |
— | — | @@ -0,0 +1,92 @@ |
| 2 | +@
|
| 3 | +@
|
| 4 | +@ Copyright 2010 TheSeven
|
| 5 | +@
|
| 6 | +@
|
| 7 | +@ This file is part of emBIOS.
|
| 8 | +@
|
| 9 | +@ emBIOS is free software: you can redistribute it and/or
|
| 10 | +@ modify it under the terms of the GNU General Public License as
|
| 11 | +@ published by the Free Software Foundation, either version 2 of the
|
| 12 | +@ License, or (at your option) any later version.
|
| 13 | +@
|
| 14 | +@ emBIOS is distributed in the hope that it will be useful,
|
| 15 | +@ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +@ See the GNU General Public License for more details.
|
| 18 | +@
|
| 19 | +@ You should have received a copy of the GNU General Public License
|
| 20 | +@ along with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +@
|
| 22 | +@
|
| 23 | +
|
| 24 | +
|
| 25 | +.section .icode.displaylcd, "ax", %progbits
|
| 26 | +.align 2
|
| 27 | +.global displaylcd
|
| 28 | +.type displaylcd, %function
|
| 29 | +displaylcd:
|
| 30 | + stmfd sp!, {r0,r1,r4,lr}
|
| 31 | + mov r12, #0x38000000
|
| 32 | + orr r12, r12, #0x300000
|
| 33 | + mov r0, #0x2a
|
| 34 | + bl displaylcd_sendlcdc
|
| 35 | + ldr r0, [sp]
|
| 36 | + bl displaylcd_sendlcdd
|
| 37 | + ldr r0, [sp,#0x04]
|
| 38 | + bl displaylcd_sendlcdd
|
| 39 | + mov r0, #0x2b
|
| 40 | + bl displaylcd_sendlcdc
|
| 41 | + mov r0, r2
|
| 42 | + tst r0, #0x100
|
| 43 | + eorne r0, #0x300
|
| 44 | + bl displaylcd_sendlcdd
|
| 45 | + mov r0, r3
|
| 46 | + tst r0, #0x100
|
| 47 | + eorne r0, #0x300
|
| 48 | + bl displaylcd_sendlcdd
|
| 49 | + mov r0, #0x2c
|
| 50 | + bl displaylcd_sendlcdc
|
| 51 | + ldmia sp, {r0,r1}
|
| 52 | + sub r1, r0
|
| 53 | + add r1, r1, #1
|
| 54 | + sub r3, r2
|
| 55 | + add r3, r3, #1
|
| 56 | + mul r2, r1, r3
|
| 57 | + ldr r1, [sp,#0x10]
|
| 58 | + cmp r1, #0x40000000
|
| 59 | + bne displaylcd_framebuf
|
| 60 | +displaylcd_color:
|
| 61 | + ldr r0, [sp,#0x14]
|
| 62 | + bl displaylcd_sendlcdd
|
| 63 | + subs r2, r2, #1
|
| 64 | + bne displaylcd_color
|
| 65 | + ldmfd sp!, {r4-r6,pc}
|
| 66 | +displaylcd_framebuf:
|
| 67 | + ldrh r0, [r1], #2
|
| 68 | + bl displaylcd_sendlcdd
|
| 69 | + subs r2, r2, #1
|
| 70 | + bne displaylcd_framebuf
|
| 71 | + ldmfd sp!, {r0,r1,r4,pc}
|
| 72 | +
|
| 73 | +displaylcd_sendlcdc:
|
| 74 | + ldrh r4, [r12,#0x1c]
|
| 75 | + tst r4, #0x10
|
| 76 | + bne displaylcd_sendlcdc
|
| 77 | + strh r0, [r12,#0x04]
|
| 78 | + mov pc, lr
|
| 79 | +displaylcd_sendlcdd:
|
| 80 | + ldrh r4, [r12,#0x1c]
|
| 81 | + tst r4, #0x10
|
| 82 | + bne displaylcd_sendlcdd
|
| 83 | + strh r0, [r12,#0x40]
|
| 84 | + mov pc, lr
|
| 85 | +.size displaylcd, .-displaylcd
|
| 86 | +
|
| 87 | +.section .icode.displaylcd_sync, "ax", %progbits
|
| 88 | +.align 2
|
| 89 | +.global displaylcd_sync
|
| 90 | +.type displaylcd_sync, %function
|
| 91 | +displaylcd_sync:
|
| 92 | + mov pc, lr
|
| 93 | +.size displaylcd_sync, .-displaylcd_sync
|
Index: embios/branches/4g_compat/target/ipodnano4g/ls.x |
— | — | @@ -0,0 +1,101 @@ |
| 2 | +ENTRY(_start)
|
| 3 | +OUTPUT_FORMAT(elf32-littlearm)
|
| 4 | +OUTPUT_ARCH(arm)
|
| 5 | +STARTUP(build/ipodnano4g/target/ipodnano4g/crt0.o)
|
| 6 | +
|
| 7 | +MEMORY
|
| 8 | +{
|
| 9 | + INIT : ORIGIN = 0x08000000, LENGTH = 0x01f00000
|
| 10 | + SRAM : ORIGIN = 0x22000000, LENGTH = 0x00030000
|
| 11 | + SDRAM : ORIGIN = 0x09f00000, LENGTH = 0x00100000
|
| 12 | +}
|
| 13 | +
|
| 14 | +SECTIONS
|
| 15 | +{
|
| 16 | + .init : {
|
| 17 | + *(.initcode*)
|
| 18 | + *(.initrodata*)
|
| 19 | + *(.initdata*)
|
| 20 | + . = ALIGN(0x4);
|
| 21 | + } > INIT
|
| 22 | +
|
| 23 | + .intvect : {
|
| 24 | + _sramstart = .;
|
| 25 | + KEEP(*(.intvect))
|
| 26 | + *(.intvect)
|
| 27 | + } > SRAM AT> INIT
|
| 28 | + _sramsource = LOADADDR(.intvect);
|
| 29 | +
|
| 30 | + .iram :
|
| 31 | + {
|
| 32 | + *(.icode*)
|
| 33 | + *(.irodata*)
|
| 34 | + *(.idata*)
|
| 35 | + . = ALIGN(0x4);
|
| 36 | + _sramend = .;
|
| 37 | + } > SRAM AT> INIT
|
| 38 | +
|
| 39 | + .text :
|
| 40 | + {
|
| 41 | + _sdramstart = .;
|
| 42 | + *(.text*)
|
| 43 | + *(.glue_7)
|
| 44 | + *(.glue_7t)
|
| 45 | + . = ALIGN(0x4);
|
| 46 | + } > SDRAM AT> INIT
|
| 47 | + _sdramsource = LOADADDR(.text);
|
| 48 | +
|
| 49 | + .rodata :
|
| 50 | + {
|
| 51 | + *(.rodata*)
|
| 52 | + . = ALIGN(0x4);
|
| 53 | + } > SDRAM AT> INIT
|
| 54 | +
|
| 55 | + .data :
|
| 56 | + {
|
| 57 | + *(.data*)
|
| 58 | + . = ALIGN(0x4);
|
| 59 | + _sdramend = .;
|
| 60 | + } > SDRAM AT> INIT
|
| 61 | +
|
| 62 | + .initbss (NOLOAD) :
|
| 63 | + {
|
| 64 | + _initbssstart = .;
|
| 65 | + *(.initbss*)
|
| 66 | + . = ALIGN(0x4);
|
| 67 | + _initstackstart = .;
|
| 68 | + . += 0x4000;
|
| 69 | + _initstackend = .;
|
| 70 | + _initbssend = .;
|
| 71 | + } > INIT
|
| 72 | +
|
| 73 | + .ibss (NOLOAD) :
|
| 74 | + {
|
| 75 | + _ibssstart = .;
|
| 76 | + *(.ibss*)
|
| 77 | + . = ALIGN(0x4);
|
| 78 | + _irqstackstart = .;
|
| 79 | + . += 0x400;
|
| 80 | + _irqstackend = .;
|
| 81 | + _abortstackstart = .;
|
| 82 | + . += 0x400;
|
| 83 | + _abortstackend = .;
|
| 84 | + *(.stack)
|
| 85 | + _ibssend = .;
|
| 86 | + } > SRAM
|
| 87 | +
|
| 88 | + .bss (NOLOAD) :
|
| 89 | + {
|
| 90 | + _bssstart = .;
|
| 91 | + *(.bss*)
|
| 92 | + *(COMMON)
|
| 93 | + . = ALIGN(0x4);
|
| 94 | + _bssend = .;
|
| 95 | + } > SDRAM
|
| 96 | +
|
| 97 | + /DISCARD/ :
|
| 98 | + {
|
| 99 | + *(.eh_frame)
|
| 100 | + }
|
| 101 | +
|
| 102 | +}
|
Index: embios/branches/4g_compat/target/ipodnano4g/mmu.h |
— | — | @@ -0,0 +1,35 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __MMU_H__
|
| 26 | +#define __MMU_H__
|
| 27 | +
|
| 28 | +
|
| 29 | +#include "global.h"
|
| 30 | +
|
| 31 | +
|
| 32 | +void clean_dcache() __attribute__((naked, noinline)) ICODE_ATTR;
|
| 33 | +void invalidate_dcache() __attribute__((naked, noinline)) ICODE_ATTR;
|
| 34 | +
|
| 35 | +
|
| 36 | +#endif
|
Index: embios/branches/4g_compat/target/ipodnano4g/storage.c |
— | — | @@ -0,0 +1,51 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +
|
| 26 | +#include "global.h"
|
| 27 | +#include "storage.h"
|
| 28 | +
|
| 29 | +uint32_t storage_init()
|
| 30 | +{
|
| 31 | + return -1;
|
| 32 | +}
|
| 33 | +
|
| 34 | +uint32_t storage_read(uint32_t sector, uint32_t count, void* buffer)
|
| 35 | +{
|
| 36 | + return -1;
|
| 37 | +}
|
| 38 | +
|
| 39 | +uint32_t storage_write(uint32_t sector, uint32_t count, const void* buffer)
|
| 40 | +{
|
| 41 | + return -1;
|
| 42 | +}
|
| 43 | +
|
| 44 | +uint32_t storage_sync()
|
| 45 | +{
|
| 46 | + return -1;
|
| 47 | +}
|
| 48 | +
|
| 49 | +uint32_t storage_get_sector_count()
|
| 50 | +{
|
| 51 | + return -1;
|
| 52 | +}
|
Index: embios/branches/4g_compat/target/ipodnano4g/timer.h |
— | — | @@ -0,0 +1,42 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __TIMER_H__
|
| 26 | +#define __TIMER_H__
|
| 27 | +
|
| 28 | +#include "global.h"
|
| 29 | +
|
| 30 | +
|
| 31 | +#define TIME_AFTER(a,b) ((long)(b) - (long)(a) < 0)
|
| 32 | +#define TIME_BEFORE(a,b) TIME_AFTER(b,a)
|
| 33 | +#define TIMEOUT_EXPIRED(a,b) TIME_AFTER(USEC_TIMER,a + b)
|
| 34 | +
|
| 35 | +
|
| 36 | +static inline void sleep(long duration) /* in usec steps */
|
| 37 | +{
|
| 38 | + long timestamp = USEC_TIMER;
|
| 39 | + while (!TIMEOUT_EXPIRED(timestamp, duration));
|
| 40 | +}
|
| 41 | +
|
| 42 | +
|
| 43 | +#endif
|
Index: embios/branches/4g_compat/target/ipodnano4g/lcd.h |
— | — | @@ -0,0 +1,43 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __LCD_H__
|
| 26 | +#define __LCD_H__
|
| 27 | +
|
| 28 | +
|
| 29 | +#include "global.h"
|
| 30 | +
|
| 31 | +
|
| 32 | +#define LCD_WIDTH 240
|
| 33 | +#define LCD_HEIGHT 320
|
| 34 | +#define LCD_FORMAT rgb565
|
| 35 | +#define LCD_BYTESPERPIXEL 2
|
| 36 | +#define LCD_FRAMEBUFSIZE (LCD_WIDTH * LCD_HEIGHT * LCD_BYTESPERPIXEL)
|
| 37 | +
|
| 38 | +
|
| 39 | +void displaylcd(unsigned int startx, unsigned int endx,
|
| 40 | + unsigned int starty, unsigned int endy, void* data, int color);
|
| 41 | +void displaylcd_sync();
|
| 42 | +
|
| 43 | +
|
| 44 | +#endif
|
Index: embios/branches/4g_compat/target/ipodnano4g/crt0.S |
— | — | @@ -0,0 +1,182 @@ |
| 2 | +@
|
| 3 | +@
|
| 4 | +@ Copyright 2010 TheSeven
|
| 5 | +@
|
| 6 | +@
|
| 7 | +@ This file is part of emBIOS.
|
| 8 | +@
|
| 9 | +@ emBIOS is free software: you can redistribute it and/or
|
| 10 | +@ modify it under the terms of the GNU General Public License as
|
| 11 | +@ published by the Free Software Foundation, either version 2 of the
|
| 12 | +@ License, or (at your option) any later version.
|
| 13 | +@
|
| 14 | +@ emBIOS is distributed in the hope that it will be useful,
|
| 15 | +@ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +@ See the GNU General Public License for more details.
|
| 18 | +@
|
| 19 | +@ You should have received a copy of the GNU General Public License
|
| 20 | +@ along with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +@
|
| 22 | +@
|
| 23 | +
|
| 24 | +
|
| 25 | +.section .intvect,"ax",%progbits
|
| 26 | + ldr pc, =reset_handler
|
| 27 | + ldr pc, =undef_instr_handler
|
| 28 | + ldr pc, =syscall_handler
|
| 29 | + ldr pc, =prefetch_abort_handler
|
| 30 | + ldr pc, =data_abort_handler
|
| 31 | + ldr pc, =reserved_handler
|
| 32 | + ldr pc, =irq_handler
|
| 33 | + ldr pc, =fiq_handler
|
| 34 | +.ltorg
|
| 35 | +
|
| 36 | +
|
| 37 | +.section .initcode,"ax",%progbits
|
| 38 | +.global _start
|
| 39 | +_start:
|
| 40 | + ldr r0, =_sramsource
|
| 41 | + ldr r1, =_sramstart
|
| 42 | + ldr r2, =_sramend
|
| 43 | +.copysram:
|
| 44 | + cmp r2, r1
|
| 45 | + ldrhi r3, [r0], #4
|
| 46 | + strhi r3, [r1], #4
|
| 47 | + bhi .copysram
|
| 48 | + ldr r0, =_sdramsource
|
| 49 | + ldr r1, =_sdramstart
|
| 50 | + ldr r2, =_sdramend
|
| 51 | +.copysdram:
|
| 52 | + cmp r2, r1
|
| 53 | + ldrhi r3, [r0], #4
|
| 54 | + strhi r3, [r1], #4
|
| 55 | + bhi .copysdram
|
| 56 | + ldr r0, =_initbssstart
|
| 57 | + ldr r1, =_initbssend
|
| 58 | + mov r2, #0
|
| 59 | +.clearinitbss:
|
| 60 | + cmp r1, r0
|
| 61 | + strhi r2, [r0], #4
|
| 62 | + bhi .clearinitbss
|
| 63 | + ldr r0, =_ibssstart
|
| 64 | + ldr r1, =_ibssend
|
| 65 | +.clearibss:
|
| 66 | + cmp r1, r0
|
| 67 | + strhi r2, [r0], #4
|
| 68 | + bhi .clearibss
|
| 69 | + ldr r0, =_bssstart
|
| 70 | + ldr r1, =_bssend
|
| 71 | +.clearbss:
|
| 72 | + cmp r1, r0
|
| 73 | + strhi r2, [r0], #4
|
| 74 | + bhi .clearbss
|
| 75 | + ldr r1, =0x38200000
|
| 76 | + ldr r0, [r1]
|
| 77 | + orr r0, r0, #1
|
| 78 | + bic r0, r0, #0x10000
|
| 79 | + str r0, [r1]
|
| 80 | + mov r0, #0
|
| 81 | + mcr p15, 0, r0,c7,c5,0
|
| 82 | + msr cpsr_c, #0xd2
|
| 83 | + ldr sp, =_irqstackend
|
| 84 | + msr cpsr_c, #0xd7
|
| 85 | + ldr sp, =_abortstackend
|
| 86 | + msr cpsr_c, #0xdb
|
| 87 | + ldr sp, =_abortstackend
|
| 88 | + msr cpsr_c, #0xd3
|
| 89 | + ldr sp, =_initstackend
|
| 90 | + bl init
|
| 91 | + b main
|
| 92 | +.ltorg
|
| 93 | +
|
| 94 | +
|
| 95 | +.section .icode, "ax", %progbits
|
| 96 | +.align 2
|
| 97 | +.global reset
|
| 98 | +.global hang
|
| 99 | +.type reset, %function
|
| 100 | +.type hang, %function
|
| 101 | +reset:
|
| 102 | + msr cpsr_c, #0xd3
|
| 103 | + mov r0, #0x100000
|
| 104 | + mov r1, #0x3c800000
|
| 105 | + str r0, [r1]
|
| 106 | +hang:
|
| 107 | + b hang
|
| 108 | +.size reset, .-reset
|
| 109 | +.size hang, .-hang
|
| 110 | +
|
| 111 | +.type reset_handler, %function
|
| 112 | +reset_handler:
|
| 113 | + adr r0, reset_text
|
| 114 | + b panic
|
| 115 | +reset_text:
|
| 116 | + .ascii "Hit reset vector!\0"
|
| 117 | +.size reset_handler, .-reset_handler
|
| 118 | +
|
| 119 | +.type undef_instr_handler, %function
|
| 120 | +undef_instr_handler:
|
| 121 | + adr r0, undef_instr_text
|
| 122 | + sub r0, lr, #4
|
| 123 | + b panicf
|
| 124 | +.size undef_instr_handler, .-undef_instr_handler
|
| 125 | +
|
| 126 | +.type prefetch_abort_handler, %function
|
| 127 | +prefetch_abort_handler:
|
| 128 | + adr r0, prefetch_abort_text
|
| 129 | + sub r0, lr, #4
|
| 130 | + b panicf
|
| 131 | +.size prefetch_abort_handler, .-prefetch_abort_handler
|
| 132 | +
|
| 133 | +.type data_abort_handler, %function
|
| 134 | +data_abort_handler:
|
| 135 | + adr r0, data_abort_text
|
| 136 | + sub r0, lr, #4
|
| 137 | + b panicf
|
| 138 | +.size data_abort_handler, .-data_abort_handler
|
| 139 | +
|
| 140 | +.type reserved_handler, %function
|
| 141 | +reserved_handler:
|
| 142 | + adr r0, reserved_text
|
| 143 | + b panic
|
| 144 | +.size reserved_handler, .-reserved_handler
|
| 145 | +
|
| 146 | +.type fiq_handler, %function
|
| 147 | +fiq_handler:
|
| 148 | + adr r0, fiq_text
|
| 149 | + b panic
|
| 150 | +.size fiq_handler, .-fiq_handler
|
| 151 | +
|
| 152 | +.type irq_handler, %function
|
| 153 | +irq_handler:
|
| 154 | + adr r0, irq_text
|
| 155 | + b panic
|
| 156 | +.size irq_handler, .-irq_handler
|
| 157 | +
|
| 158 | +.type syscall_handler, %function
|
| 159 | +syscall_handler:
|
| 160 | + adr r0, syscall_text
|
| 161 | + b panic
|
| 162 | +.size syscall_handler, .-syscall_handler
|
| 163 | +
|
| 164 | +undef_instr_text:
|
| 165 | + .ascii "Undefined instruction at %08X!\0"
|
| 166 | +
|
| 167 | +prefetch_abort_text:
|
| 168 | + .ascii "Prefetch abort at %08X!\0"
|
| 169 | +
|
| 170 | +data_abort_text:
|
| 171 | + .ascii "Data abort at %08X!\0"
|
| 172 | +
|
| 173 | +reserved_text:
|
| 174 | + .ascii "Hit reserved exception handler!\0"
|
| 175 | +
|
| 176 | +fiq_text:
|
| 177 | + .ascii "Unhandled FIQ!\0"
|
| 178 | +
|
| 179 | +irq_text:
|
| 180 | + .ascii "Unhandled IRQ!\0"
|
| 181 | +
|
| 182 | +syscall_text:
|
| 183 | + .ascii "Unhandled syscall!\0"
|
Index: embios/branches/4g_compat/target/ipodnano4g/storage.h |
— | — | @@ -0,0 +1,36 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __FTL_H__
|
| 26 | +#define __FTL_H__
|
| 27 | +
|
| 28 | +#include "global.h"
|
| 29 | +
|
| 30 | +uint32_t storage_init();
|
| 31 | +uint32_t storage_read(uint32_t sector, uint32_t count, void* buffer);
|
| 32 | +uint32_t storage_write(uint32_t sector, uint32_t count, const void* buffer);
|
| 33 | +uint32_t storage_sync();
|
| 34 | +uint32_t storage_get_sector_count();
|
| 35 | +
|
| 36 | +
|
| 37 | +#endif
|
Index: embios/branches/4g_compat/target/ipodnano4g/config.h |
— | — | @@ -0,0 +1,28 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2009 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of the Linux4Nano toolkit.
|
| 8 | +//
|
| 9 | +// TheSeven's iBugger is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// TheSeven's iBugger is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with the Linux4Nano toolkit. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +//#define NAND_DEBUG
|
| 26 | +//#define NAND_TRACE
|
| 27 | +//#define VFL_TRACE
|
| 28 | +//#define FTL_TRACE
|
| 29 | +
|
Index: embios/branches/4g_compat/target/ipodnano4g/target.h |
— | — | @@ -0,0 +1,31 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __TARGET_H__
|
| 26 | +#define __TARGET_H__
|
| 27 | +
|
| 28 | +
|
| 29 | +#define ARM_ARCH 6
|
| 30 | +
|
| 31 | +
|
| 32 | +#endif
|
Index: embios/branches/4g_compat/target/ipodnano2g/lcd.S |
— | — | @@ -0,0 +1,165 @@ |
| 2 | +@
|
| 3 | +@
|
| 4 | +@ Copyright 2010 TheSeven
|
| 5 | +@
|
| 6 | +@
|
| 7 | +@ This file is part of emBIOS.
|
| 8 | +@
|
| 9 | +@ emBIOS is free software: you can redistribute it and/or
|
| 10 | +@ modify it under the terms of the GNU General Public License as
|
| 11 | +@ published by the Free Software Foundation, either version 2 of the
|
| 12 | +@ License, or (at your option) any later version.
|
| 13 | +@
|
| 14 | +@ emBIOS is distributed in the hope that it will be useful,
|
| 15 | +@ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +@ See the GNU General Public License for more details.
|
| 18 | +@
|
| 19 | +@ You should have received a copy of the GNU General Public License
|
| 20 | +@ along with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +@
|
| 22 | +@
|
| 23 | +
|
| 24 | +
|
| 25 | +.section .icode.displaylcd, "ax", %progbits
|
| 26 | +.align 2
|
| 27 | +.global displaylcd
|
| 28 | +.type displaylcd, %function
|
| 29 | +displaylcd:
|
| 30 | + stmfd sp!, {r0,r1,r4,lr}
|
| 31 | + bl displaylcd_sync
|
| 32 | + bl displaylcd_detectlcd
|
| 33 | + sub r12, r12, #0x04900000
|
| 34 | + cmp r0, #2
|
| 35 | + bne displaylcd_othertypes
|
| 36 | + mov r0, #0x50
|
| 37 | + bl displaylcd_sendlcd2c
|
| 38 | + ldr r0, [sp]
|
| 39 | + bl displaylcd_sendlcd2d
|
| 40 | + mov r0, #0x51
|
| 41 | + bl displaylcd_sendlcd2c
|
| 42 | + ldr r0, [sp,#0x04]
|
| 43 | + bl displaylcd_sendlcd2d
|
| 44 | + mov r0, #0x52
|
| 45 | + bl displaylcd_sendlcd2c
|
| 46 | + mov r0, r2
|
| 47 | + bl displaylcd_sendlcd2d
|
| 48 | + mov r0, #0x53
|
| 49 | + bl displaylcd_sendlcd2c
|
| 50 | + mov r0, r3
|
| 51 | + bl displaylcd_sendlcd2d
|
| 52 | + mov r0, #0x20
|
| 53 | + bl displaylcd_sendlcd2c
|
| 54 | + ldr r0, [sp]
|
| 55 | + bl displaylcd_sendlcd2d
|
| 56 | + mov r0, #0x21
|
| 57 | + bl displaylcd_sendlcd2c
|
| 58 | + mov r0, r2
|
| 59 | + bl displaylcd_sendlcd2d
|
| 60 | + mov r0, #0x22
|
| 61 | + bl displaylcd_sendlcd2c
|
| 62 | + b displaylcd_blit
|
| 63 | +displaylcd_othertypes:
|
| 64 | + mov r0, #0x2a
|
| 65 | + bl displaylcd_sendlcdc
|
| 66 | + ldr r0, [sp]
|
| 67 | + bl displaylcd_sendlcd2d
|
| 68 | + ldr r0, [sp,#0x04]
|
| 69 | + bl displaylcd_sendlcd2d
|
| 70 | + mov r0, #0x2b
|
| 71 | + bl displaylcd_sendlcdc
|
| 72 | + mov r0, r2
|
| 73 | + bl displaylcd_sendlcd2d
|
| 74 | + mov r0, r3
|
| 75 | + bl displaylcd_sendlcd2d
|
| 76 | + mov r0, #0x2c
|
| 77 | + bl displaylcd_sendlcdc
|
| 78 | +displaylcd_blit:
|
| 79 | + ldmia sp, {r0,r1}
|
| 80 | + sub r1, r0
|
| 81 | + add r1, r1, #1
|
| 82 | + sub r3, r2
|
| 83 | + add r3, r3, #1
|
| 84 | + mul r2, r1, r3
|
| 85 | + ldr r1, [sp,#0x10]
|
| 86 | + cmp r1, #0x40000000
|
| 87 | + bne displaylcd_dma
|
| 88 | +displaylcd_pixel:
|
| 89 | + ldr r0, [sp,#0x14]
|
| 90 | + bl displaylcd_sendlcd2d
|
| 91 | + subs r2, r2, #1
|
| 92 | + bne displaylcd_pixel
|
| 93 | + ldmfd sp!, {r0,r1,r4,pc}
|
| 94 | +displaylcd_dma:
|
| 95 | + mov r4, #0x38000000
|
| 96 | + add r4, r4, #0x400000
|
| 97 | + mov r0, #0x20000000
|
| 98 | + orr r0, r0, #0x180000
|
| 99 | + str r0, [r4,#0x104]
|
| 100 | + str r1, [r4,#0x100]
|
| 101 | + mov r0, r2,lsr#1
|
| 102 | + sub r0, r0, #1
|
| 103 | + str r0, [r4,#0x108]
|
| 104 | + bl clean_dcache
|
| 105 | + mov r0, #4
|
| 106 | + str r0, [r4,#0x114]
|
| 107 | + ldmfd sp!, {r0,r1,r4,pc}
|
| 108 | +
|
| 109 | +displaylcd_sendlcd2c:
|
| 110 | + ldr r4, [r12,#0x1c]
|
| 111 | + tst r4, #0x10
|
| 112 | + bne displaylcd_sendlcd2c
|
| 113 | + mov r4, r0,lsr#8
|
| 114 | + str r4, [r12,#0x04]
|
| 115 | + and r0, r0, #0xff
|
| 116 | +displaylcd_sendlcdc:
|
| 117 | + ldrh r4, [r12,#0x1c]
|
| 118 | + tst r4, #0x10
|
| 119 | + bne displaylcd_sendlcdc
|
| 120 | + strh r0, [r12,#0x04]
|
| 121 | + mov pc, lr
|
| 122 | +displaylcd_sendlcd2d:
|
| 123 | + ldrh r4, [r12,#0x1c]
|
| 124 | + tst r4, #0x10
|
| 125 | + bne displaylcd_sendlcd2d
|
| 126 | + mov r4, r0,lsr#8
|
| 127 | + strh r4, [r12,#0x40]
|
| 128 | + and r0, r0, #0xff
|
| 129 | +displaylcd_sendlcdd:
|
| 130 | + ldrh r4, [r12,#0x1c]
|
| 131 | + tst r4, #0x10
|
| 132 | + bne displaylcd_sendlcdd
|
| 133 | + strh r0, [r12,#0x40]
|
| 134 | + mov pc, lr
|
| 135 | +
|
| 136 | +displaylcd_detectlcd:
|
| 137 | + mov r12, #0x3c000000
|
| 138 | + orr r12, r12, #0xf00000
|
| 139 | + ldr r0, [r12,#0xd0]
|
| 140 | + bic r0, r0, #0x0f
|
| 141 | + str r0, [r12,#0xd0]
|
| 142 | + ldr r0, [r12,#0xe0]
|
| 143 | + bic r0, r0, #0xf0
|
| 144 | + str r0, [r12,#0xe0]
|
| 145 | + ldr r0, [r12,#0xd4]
|
| 146 | + and r0, r0, #1
|
| 147 | + ldr r1, [r12,#0xe4]
|
| 148 | + and r1, r1, #2
|
| 149 | + orr r0, r0, r1
|
| 150 | + mov pc, lr
|
| 151 | +.size displaylcd, .-displaylcd
|
| 152 | +
|
| 153 | +
|
| 154 | +.section .icode.displaylcd_sync, "ax", %progbits
|
| 155 | +.align 2
|
| 156 | +.global displaylcd_sync
|
| 157 | +.type displaylcd_sync, %function
|
| 158 | +displaylcd_sync:
|
| 159 | + mov r1, #0x38000000
|
| 160 | + add r1, r1, #0x400000
|
| 161 | +displaylcd_sync_wait:
|
| 162 | + ldr r0, [r1,#0x184]
|
| 163 | + tst r0, #0x40000
|
| 164 | + bne displaylcd_sync_wait
|
| 165 | + mov pc, lr
|
| 166 | +.size displaylcd_sync, .-displaylcd_sync
|
Index: embios/branches/4g_compat/target/ipodnano2g/mmu.c |
— | — | @@ -0,0 +1,64 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#include "global.h"
|
| 26 | +#include "mmu.h"
|
| 27 | +
|
| 28 | +
|
| 29 | +void clean_dcache()
|
| 30 | +{
|
| 31 | + asm volatile(
|
| 32 | + "MOV R0, #0 \n\t"
|
| 33 | + "clean_dcache_loop: \n\t"
|
| 34 | + "MCR p15, 0, R0,c7,c10,2 \n\t"
|
| 35 | + "ADD R1, R0, #0x10 \n\t"
|
| 36 | + "MCR p15, 0, R1,c7,c10,2 \n\t"
|
| 37 | + "ADD R1, R1, #0x10 \n\t"
|
| 38 | + "MCR p15, 0, R1,c7,c10,2 \n\t"
|
| 39 | + "ADD R1, R1, #0x10 \n\t"
|
| 40 | + "MCR p15, 0, R1,c7,c10,2 \n\t"
|
| 41 | + "ADDS R0, R0, #0x04000000 \n\t"
|
| 42 | + "BNE clean_dcache_loop \n\t"
|
| 43 | + "MCR p15, 0, R0,c7,c10,4 \n\t"
|
| 44 | + "MOV PC, LR \n\t"
|
| 45 | + );
|
| 46 | +}
|
| 47 | +
|
| 48 | +void invalidate_dcache()
|
| 49 | +{
|
| 50 | + asm volatile(
|
| 51 | + "MOV R0, #0 \n\t"
|
| 52 | + "invalidate_dcache_loop: \n\t"
|
| 53 | + "MCR p15, 0, R0,c7,c14,2 \n\t"
|
| 54 | + "ADD R1, R0, #0x10 \n\t"
|
| 55 | + "MCR p15, 0, R1,c7,c14,2 \n\t"
|
| 56 | + "ADD R1, R1, #0x10 \n\t"
|
| 57 | + "MCR p15, 0, R1,c7,c14,2 \n\t"
|
| 58 | + "ADD R1, R1, #0x10 \n\t"
|
| 59 | + "MCR p15, 0, R1,c7,c14,2 \n\t"
|
| 60 | + "ADDS R0, R0, #0x04000000 \n\t"
|
| 61 | + "BNE invalidate_dcache_loop\n\t"
|
| 62 | + "MCR p15, 0, R0,c7,c10,4 \n\t"
|
| 63 | + "MOV PC, LR \n\t"
|
| 64 | + );
|
| 65 | +}
|
Index: embios/branches/4g_compat/target/ipodnano2g/ls.x |
— | — | @@ -0,0 +1,101 @@ |
| 2 | +ENTRY(_start)
|
| 3 | +OUTPUT_FORMAT(elf32-littlearm)
|
| 4 | +OUTPUT_ARCH(arm)
|
| 5 | +STARTUP(build/ipodnano2g/target/ipodnano2g/crt0.o)
|
| 6 | +
|
| 7 | +MEMORY
|
| 8 | +{
|
| 9 | + INIT : ORIGIN = 0x08000000, LENGTH = 0x01f00000
|
| 10 | + SRAM : ORIGIN = 0x22000000, LENGTH = 0x0002bdf0
|
| 11 | + SDRAM : ORIGIN = 0x09f00000, LENGTH = 0x00100000
|
| 12 | +}
|
| 13 | +
|
| 14 | +SECTIONS
|
| 15 | +{
|
| 16 | + .init : {
|
| 17 | + *(.initcode*)
|
| 18 | + *(.initrodata*)
|
| 19 | + *(.initdata*)
|
| 20 | + . = ALIGN(0x4);
|
| 21 | + } > INIT
|
| 22 | +
|
| 23 | + .intvect : {
|
| 24 | + _sramstart = .;
|
| 25 | + KEEP(*(.intvect))
|
| 26 | + *(.intvect)
|
| 27 | + } > SRAM AT> INIT
|
| 28 | + _sramsource = LOADADDR(.intvect);
|
| 29 | +
|
| 30 | + .iram :
|
| 31 | + {
|
| 32 | + *(.icode*)
|
| 33 | + *(.irodata*)
|
| 34 | + *(.idata*)
|
| 35 | + . = ALIGN(0x4);
|
| 36 | + _sramend = .;
|
| 37 | + } > SRAM AT> INIT
|
| 38 | +
|
| 39 | + .text :
|
| 40 | + {
|
| 41 | + _sdramstart = .;
|
| 42 | + *(.text*)
|
| 43 | + *(.glue_7)
|
| 44 | + *(.glue_7t)
|
| 45 | + . = ALIGN(0x4);
|
| 46 | + } > SDRAM AT> INIT
|
| 47 | + _sdramsource = LOADADDR(.text);
|
| 48 | +
|
| 49 | + .rodata :
|
| 50 | + {
|
| 51 | + *(.rodata*)
|
| 52 | + . = ALIGN(0x4);
|
| 53 | + } > SDRAM AT> INIT
|
| 54 | +
|
| 55 | + .data :
|
| 56 | + {
|
| 57 | + *(.data*)
|
| 58 | + . = ALIGN(0x4);
|
| 59 | + _sdramend = .;
|
| 60 | + } > SDRAM AT> INIT
|
| 61 | +
|
| 62 | + .initbss (NOLOAD) :
|
| 63 | + {
|
| 64 | + _initbssstart = .;
|
| 65 | + *(.initbss*)
|
| 66 | + . = ALIGN(0x4);
|
| 67 | + _initstackstart = .;
|
| 68 | + . += 0x4000;
|
| 69 | + _initstackend = .;
|
| 70 | + _initbssend = .;
|
| 71 | + } > INIT
|
| 72 | +
|
| 73 | + .ibss (NOLOAD) :
|
| 74 | + {
|
| 75 | + _ibssstart = .;
|
| 76 | + *(.ibss*)
|
| 77 | + . = ALIGN(0x4);
|
| 78 | + _irqstackstart = .;
|
| 79 | + . += 0x400;
|
| 80 | + _irqstackend = .;
|
| 81 | + _abortstackstart = .;
|
| 82 | + . += 0x400;
|
| 83 | + _abortstackend = .;
|
| 84 | + *(.stack)
|
| 85 | + _ibssend = .;
|
| 86 | + } > SRAM
|
| 87 | +
|
| 88 | + .bss (NOLOAD) :
|
| 89 | + {
|
| 90 | + _bssstart = .;
|
| 91 | + *(.bss*)
|
| 92 | + *(COMMON)
|
| 93 | + . = ALIGN(0x4);
|
| 94 | + _bssend = .;
|
| 95 | + } > SDRAM
|
| 96 | +
|
| 97 | + /DISCARD/ :
|
| 98 | + {
|
| 99 | + *(.eh_frame)
|
| 100 | + }
|
| 101 | +
|
| 102 | +}
|
Index: embios/branches/4g_compat/target/ipodnano2g/mmu.h |
— | — | @@ -0,0 +1,35 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __MMU_H__
|
| 26 | +#define __MMU_H__
|
| 27 | +
|
| 28 | +
|
| 29 | +#include "global.h"
|
| 30 | +
|
| 31 | +
|
| 32 | +void clean_dcache() __attribute__((naked, noinline)) ICODE_ATTR;
|
| 33 | +void invalidate_dcache() __attribute__((naked, noinline)) ICODE_ATTR;
|
| 34 | +
|
| 35 | +
|
| 36 | +#endif
|
Index: embios/branches/4g_compat/target/ipodnano2g/storage.c |
— | — | @@ -0,0 +1,1848 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +
|
| 26 | +#include "global.h"
|
| 27 | +#include "nand.h"
|
| 28 | +#include "storage.h"
|
| 29 | +#include "util.h"
|
| 30 | +
|
| 31 | +
|
| 32 | +
|
| 33 | +//#define FTL_FORCEMOUNT
|
| 34 | +
|
| 35 | +
|
| 36 | +
|
| 37 | +#ifdef FTL_FORCEMOUNT
|
| 38 | +#ifndef FTL_READONLY
|
| 39 | +#define FTL_READONLY
|
| 40 | +#endif
|
| 41 | +#endif
|
| 42 | +
|
| 43 | +
|
| 44 | +#ifdef FTL_READONLY
|
| 45 | +uint32_t storage_write(uint32_t sector, uint32_t count, const void* buffer)
|
| 46 | +{
|
| 47 | + (void)sector;
|
| 48 | + (void)count;
|
| 49 | + (void)buffer;
|
| 50 | + return -1;
|
| 51 | +}
|
| 52 | +uint32_t storage_sync(void)
|
| 53 | +{
|
| 54 | + return 0;
|
| 55 | +}
|
| 56 | +#endif
|
| 57 | +
|
| 58 | +
|
| 59 | +
|
| 60 | +/* Keeps the state of a scattered page block.
|
| 61 | + This structure is used in memory only, not on flash,
|
| 62 | + but it equals the one the OFW uses. */
|
| 63 | +struct ftl_log_type
|
| 64 | +{
|
| 65 | +
|
| 66 | + /* The ftl_cxt.nextblockusn at the time the block was allocated,
|
| 67 | + needed in order to be able to remove the oldest ones first. */
|
| 68 | + uint32_t usn;
|
| 69 | +
|
| 70 | + /* The vBlock number at which the scattered pages are stored */
|
| 71 | + uint16_t scatteredvblock;
|
| 72 | +
|
| 73 | + /* the lBlock number for which those pages are */
|
| 74 | + uint16_t logicalvblock;
|
| 75 | +
|
| 76 | + /* Pointer to ftl_offsets, contains the mapping which lPage is
|
| 77 | + currently stored at which scattered vPage. */
|
| 78 | + uint16_t* pageoffsets;
|
| 79 | +
|
| 80 | + /* Pages used in the vBlock, i.e. next page number to be written */
|
| 81 | + uint16_t pagesused;
|
| 82 | +
|
| 83 | + /* Pages that are still up to date in this block, i.e. need to be
|
| 84 | + moved when this vBlock is deallocated. */
|
| 85 | + uint16_t pagescurrent;
|
| 86 | +
|
| 87 | + /* A flag whether all pages are still sequential in this block.
|
| 88 | + Initialized to 1 on allocation, zeroed as soon as anything is
|
| 89 | + written out of sequence, so that the block will need copying
|
| 90 | + when committing to get the pages back into the right order.
|
| 91 | + This is used to half the number of block erases needed when
|
| 92 | + writing huge amounts of sequential data. */
|
| 93 | + uint32_t issequential;
|
| 94 | +
|
| 95 | +} __attribute__((packed));
|
| 96 | +
|
| 97 | +
|
| 98 | +/* Keeps the state of the FTL, both on flash and in memory */
|
| 99 | +struct ftl_cxt_type
|
| 100 | +{
|
| 101 | +
|
| 102 | + /* Update sequence number of the FTL context, decremented
|
| 103 | + every time a new revision of FTL meta data is written. */
|
| 104 | + uint32_t usn;
|
| 105 | +
|
| 106 | + /* Update sequence number for user data blocks. Incremented
|
| 107 | + every time a portion of user pages is written, so that
|
| 108 | + a consistency check can determine which copy of a user
|
| 109 | + page is the most recent one. */
|
| 110 | + uint32_t nextblockusn;
|
| 111 | +
|
| 112 | + /* Count of currently free pages in the block pool */
|
| 113 | + uint16_t freecount;
|
| 114 | +
|
| 115 | + /* Index to the first free block in the blockpool ring buffer */
|
| 116 | + uint16_t nextfreeidx;
|
| 117 | +
|
| 118 | + /* This is a counter that is used to better distribute block
|
| 119 | + wear. It is incremented on every block erase, and if it
|
| 120 | + gets too high (300 on writes, 20 on sync), the most and
|
| 121 | + least worn block will be swapped (inferring an additional
|
| 122 | + block write) and the counter will be decreased by 20. */
|
| 123 | + uint16_t swapcounter;
|
| 124 | +
|
| 125 | + /* Ring buffer of currently free blocks. nextfreeidx is the
|
| 126 | + index to freecount free ones, the other ones are currently
|
| 127 | + allocated for scattered page blocks. */
|
| 128 | + uint16_t blockpool[0x14];
|
| 129 | +
|
| 130 | + /* Alignment to 32 bits */
|
| 131 | + uint16_t field_36;
|
| 132 | +
|
| 133 | + /* vPages where the block map is stored */
|
| 134 | + uint32_t ftl_map_pages[8];
|
| 135 | +
|
| 136 | + /* Probably additional map page number space for bigger chips */
|
| 137 | + uint8_t field_58[0x28];
|
| 138 | +
|
| 139 | + /* vPages where the erase counters are stored */
|
| 140 | + uint32_t ftl_erasectr_pages[8];
|
| 141 | +
|
| 142 | + /* Seems to be padding */
|
| 143 | + uint8_t field_A0[0x70];
|
| 144 | +
|
| 145 | + /* Pointer to ftl_map used by Whimory, not used by us */
|
| 146 | + uint32_t ftl_map_ptr;
|
| 147 | +
|
| 148 | + /* Pointer to ftl_erasectr used by Whimory, not used by us */
|
| 149 | + uint32_t ftl_erasectr_ptr;
|
| 150 | +
|
| 151 | + /* Pointer to ftl_log used by Whimory, not used by us */
|
| 152 | + uint32_t ftl_log_ptr;
|
| 153 | +
|
| 154 | + /* Flag used to indicate that some erase counter pages should be committed
|
| 155 | + as they were changed more than 100 times since the last commit. */
|
| 156 | + uint32_t erasedirty;
|
| 157 | +
|
| 158 | + /* Seems to be unused */
|
| 159 | + uint16_t field_120;
|
| 160 | +
|
| 161 | + /* vBlocks used to store the FTL context, map, and erase
|
| 162 | + counter pages. This is also a ring buffer, and the oldest
|
| 163 | + page gets swapped with the least used page from the block
|
| 164 | + pool ring buffer when a new one is allocated. */
|
| 165 | + uint16_t ftlctrlblocks[3];
|
| 166 | +
|
| 167 | + /* The last used vPage number from ftlctrlblocks */
|
| 168 | + uint32_t ftlctrlpage;
|
| 169 | +
|
| 170 | + /* Set on context sync, reset on write, so obviously never
|
| 171 | + zero in the context written to the flash */
|
| 172 | + uint32_t clean_flag;
|
| 173 | +
|
| 174 | + /* Seems to be unused, but gets loaded from flash by Whimory. */
|
| 175 | + uint8_t field_130[0x15C];
|
| 176 | +
|
| 177 | +} __attribute__((packed));
|
| 178 | +
|
| 179 | +
|
| 180 | +/* Keeps the state of the bank's VFL, both on flash and in memory.
|
| 181 | + There is one of these per bank. */
|
| 182 | +struct ftl_vfl_cxt_type
|
| 183 | +{
|
| 184 | +
|
| 185 | + /* Cross-bank update sequence number, incremented on every VFL
|
| 186 | + context commit on any bank. */
|
| 187 | + uint32_t usn;
|
| 188 | +
|
| 189 | + /* See ftl_cxt.ftlctrlblocks. This is stored to the VFL contexts
|
| 190 | + in order to be able to find the most recent FTL context copy
|
| 191 | + when mounting the FTL. The VFL context number this will be
|
| 192 | + written to on an FTL context commit is chosen semi-randomly. */
|
| 193 | + uint16_t ftlctrlblocks[3];
|
| 194 | +
|
| 195 | + /* Alignment to 32 bits */
|
| 196 | + uint8_t field_A[2];
|
| 197 | +
|
| 198 | + /* Decrementing update counter for VFL context commits per bank */
|
| 199 | + uint32_t updatecount;
|
| 200 | +
|
| 201 | + /* Number of the currently active VFL context block, it's an index
|
| 202 | + into vflcxtblocks. */
|
| 203 | + uint16_t activecxtblock;
|
| 204 | +
|
| 205 | + /* Number of the first free page in the active FTL context block */
|
| 206 | + uint16_t nextcxtpage;
|
| 207 | +
|
| 208 | + /* Seems to be unused */
|
| 209 | + uint8_t field_14[4];
|
| 210 | +
|
| 211 | + /* Incremented every time a block erase error leads to a remap,
|
| 212 | + but doesn't seem to be read anywhere. */
|
| 213 | + uint16_t field_18;
|
| 214 | +
|
| 215 | + /* Number of spare blocks used */
|
| 216 | + uint16_t spareused;
|
| 217 | +
|
| 218 | + /* pBlock number of the first spare block */
|
| 219 | + uint16_t firstspare;
|
| 220 | +
|
| 221 | + /* Total number of spare blocks */
|
| 222 | + uint16_t sparecount;
|
| 223 | +
|
| 224 | + /* Block remap table. Contains the vBlock number the n-th spare
|
| 225 | + block is used as a replacement for. 0 = unused, 0xFFFF = bad. */
|
| 226 | + uint16_t remaptable[0x334];
|
| 227 | +
|
| 228 | + /* Bad block table. Each bit represents 8 blocks. 1 = OK, 0 = Bad.
|
| 229 | + If the entry is zero, you should look at the remap table to see
|
| 230 | + if the block is remapped, and if yes, where the replacement is. */
|
| 231 | + uint8_t bbt[0x11A];
|
| 232 | +
|
| 233 | + /* pBlock numbers used to store the VFL context. This is a ring
|
| 234 | + buffer. On a VFL context write, always 8 pages are written,
|
| 235 | + and it passes if at least 4 of them can be read back. */
|
| 236 | + uint16_t vflcxtblocks[4];
|
| 237 | +
|
| 238 | + /* Blocks scheduled for remapping are stored at the end of the
|
| 239 | + remap table. This is the first index used for them. */
|
| 240 | + uint16_t scheduledstart;
|
| 241 | +
|
| 242 | + /* Probably padding */
|
| 243 | + uint8_t field_7AC[0x4C];
|
| 244 | +
|
| 245 | + /* First checksum (addition) */
|
| 246 | + uint32_t checksum1;
|
| 247 | +
|
| 248 | + /* Second checksum (XOR), there is a bug in whimory regarding this. */
|
| 249 | + uint32_t checksum2;
|
| 250 | +
|
| 251 | +} __attribute__((packed));
|
| 252 | +
|
| 253 | +
|
| 254 | +/* Layout of the spare bytes of each page on the flash */
|
| 255 | +union ftl_spare_data_type
|
| 256 | +{
|
| 257 | +
|
| 258 | + /* The layout used for actual user data (types 0x40 and 0x41) */
|
| 259 | + struct ftl_spare_data_user_type
|
| 260 | + {
|
| 261 | +
|
| 262 | + /* The lPage, i.e. Sector, number */
|
| 263 | + uint32_t lpn;
|
| 264 | +
|
| 265 | + /* The update sequence number of that page,
|
| 266 | + copied from ftl_cxt.nextblockusn on write */
|
| 267 | + uint32_t usn;
|
| 268 | +
|
| 269 | + /* Seems to be unused */
|
| 270 | + uint8_t field_8;
|
| 271 | +
|
| 272 | + /* Type field, 0x40 (data page) or 0x41 (last data page of block) */
|
| 273 | + uint8_t type;
|
| 274 | +
|
| 275 | + /* ECC mark, usually 0xFF. If an error occurred while reading the
|
| 276 | + page during a copying operation earlier, this will be 0x55. */
|
| 277 | + uint8_t eccmark;
|
| 278 | +
|
| 279 | + /* Seems to be unused */
|
| 280 | + uint8_t field_B;
|
| 281 | +
|
| 282 | + /* ECC data for the user data */
|
| 283 | + uint8_t dataecc[0x28];
|
| 284 | +
|
| 285 | + /* ECC data for the first 0xC bytes above */
|
| 286 | + uint8_t spareecc[0xC];
|
| 287 | +
|
| 288 | + } __attribute__((packed)) user;
|
| 289 | +
|
| 290 | + /* The layout used for meta data (other types) */
|
| 291 | + struct ftl_spare_data_meta_type
|
| 292 | + {
|
| 293 | +
|
| 294 | + /* ftl_cxt.usn for FTL stuff, ftl_vfl_cxt.updatecount for VFL stuff */
|
| 295 | + uint32_t usn;
|
| 296 | +
|
| 297 | + /* Index of the thing inside the page,
|
| 298 | + for example number / index of the map or erase counter page */
|
| 299 | + uint16_t idx;
|
| 300 | +
|
| 301 | + /* Seems to be unused */
|
| 302 | + uint8_t field_6;
|
| 303 | +
|
| 304 | + /* Seems to be unused */
|
| 305 | + uint8_t field_7;
|
| 306 | +
|
| 307 | + /* Seems to be unused */
|
| 308 | + uint8_t field_8;
|
| 309 | +
|
| 310 | + /* Type field:
|
| 311 | + 0x43: FTL context page
|
| 312 | + 0x44: Block map page
|
| 313 | + 0x46: Erase counter page
|
| 314 | + 0x47: "FTL is currently mounted", i.e. unclean shutdown, mark
|
| 315 | + 0x80: VFL context page */
|
| 316 | + uint8_t type;
|
| 317 | +
|
| 318 | + /* ECC mark, usually 0xFF. If an error occurred while reading the
|
| 319 | + page during a copying operation earlier, this will be 0x55. */
|
| 320 | + uint8_t eccmark;
|
| 321 | +
|
| 322 | + /* Seems to be unused */
|
| 323 | + uint8_t field_B;
|
| 324 | +
|
| 325 | + /* ECC data for the user data */
|
| 326 | + uint8_t dataecc[0x28];
|
| 327 | +
|
| 328 | + /* ECC data for the first 0xC bytes above */
|
| 329 | + uint8_t spareecc[0xC];
|
| 330 | +
|
| 331 | + } __attribute__((packed)) meta;
|
| 332 | +
|
| 333 | +};
|
| 334 | +
|
| 335 | +
|
| 336 | +/* Keeps track of troublesome blocks, only in memory, lost on unmount. */
|
| 337 | +struct ftl_trouble_type
|
| 338 | +{
|
| 339 | +
|
| 340 | + /* vBlock number of the block giving trouble */
|
| 341 | + uint16_t block;
|
| 342 | +
|
| 343 | + /* Bank of the block giving trouble */
|
| 344 | + uint8_t bank;
|
| 345 | +
|
| 346 | + /* Error counter, incremented by 3 on error, decremented by 1 on erase,
|
| 347 | + remaping will be done when it reaches 6. */
|
| 348 | + uint8_t errors;
|
| 349 | +
|
| 350 | +} __attribute__((packed));
|
| 351 | +
|
| 352 | +
|
| 353 | +
|
| 354 | +/* Pointer to an info structure regarding the flash type used */
|
| 355 | +const struct nand_device_info_type* ftl_nand_type;
|
| 356 | +
|
| 357 | +/* Number of banks we detected a chip on */
|
| 358 | +uint32_t ftl_banks;
|
| 359 | +
|
| 360 | +/* Block map, used vor pBlock to vBlock mapping */
|
| 361 | +uint16_t ftl_map[0x2000];
|
| 362 | +
|
| 363 | +/* VFL context for each bank */
|
| 364 | +struct ftl_vfl_cxt_type ftl_vfl_cxt[4];
|
| 365 | +
|
| 366 | +/* FTL context */
|
| 367 | +struct ftl_cxt_type ftl_cxt;
|
| 368 | +
|
| 369 | +/* Temporary data buffers for internal use by the FTL */
|
| 370 | +uint8_t ftl_buffer[0x800] __attribute__((aligned(16)));
|
| 371 | +
|
| 372 | +/* Temporary spare byte buffer for internal use by the FTL */
|
| 373 | +union ftl_spare_data_type ftl_sparebuffer __attribute__((aligned(16)));
|
| 374 | +
|
| 375 | +uint32_t ftl_initialized;
|
| 376 | +
|
| 377 | +
|
| 378 | +#ifndef FTL_READONLY
|
| 379 | +
|
| 380 | +/* Lowlevel BBT for each bank */
|
| 381 | +uint8_t ftl_bbt[4][0x410];
|
| 382 | +
|
| 383 | +/* Erase countes for the vBlocks */
|
| 384 | +uint16_t ftl_erasectr[0x2000];
|
| 385 | +
|
| 386 | +/* Used by ftl_log */
|
| 387 | +uint16_t ftl_offsets[0x11][0x200];
|
| 388 | +
|
| 389 | +/* Structs keeping record of scattered page blocks */
|
| 390 | +struct ftl_log_type ftl_log[0x11];
|
| 391 | +
|
| 392 | +/* Global cross-bank update sequence number of the VFL context */
|
| 393 | +uint32_t ftl_vfl_usn;
|
| 394 | +
|
| 395 | +/* Keeps track (temporarily) of troublesome blocks */
|
| 396 | +struct ftl_trouble_type ftl_troublelog[5];
|
| 397 | +
|
| 398 | +/* Counts erase counter page changes, after 100 of them the affected
|
| 399 | + page will be committed to the flash. */
|
| 400 | +uint8_t ftl_erasectr_dirt[8];
|
| 401 | +
|
| 402 | +/* Buffer needed for copying pages around while moving or committing blocks.
|
| 403 | + This can't be shared with ftl_buffer, because this one could be overwritten
|
| 404 | + during the copying operation in order to e.g. commit a CXT. */
|
| 405 | +uint8_t ftl_copybuffer[0x800] __attribute__((aligned(16)));
|
| 406 | +
|
| 407 | +/* Needed to store the old scattered page offsets in order to be able to roll
|
| 408 | + back if something fails while compacting a scattered page block. */
|
| 409 | +uint16_t ftl_offsets_backup[0x200] __attribute__((aligned(16)));
|
| 410 | +
|
| 411 | +#endif
|
| 412 | +
|
| 413 | +
|
| 414 | +
|
| 415 | +
|
| 416 | +
|
| 417 | +/* Finds a device info page for the specified bank and returns its number.
|
| 418 | + Used to check if one is present, and to read the lowlevel BBT. */
|
| 419 | +uint32_t ftl_find_devinfo(uint32_t bank)
|
| 420 | +{
|
| 421 | + /* Scan the last 10% of the flash for device info pages */
|
| 422 | + uint32_t lowestBlock = (*ftl_nand_type).blocks
|
| 423 | + - ((*ftl_nand_type).blocks / 10);
|
| 424 | + uint32_t block, page, pagenum;
|
| 425 | + for (block = (*ftl_nand_type).blocks - 1; block >= lowestBlock; block--)
|
| 426 | + {
|
| 427 | + page = (*ftl_nand_type).pagesperblock - 8;
|
| 428 | + for (; page < (*ftl_nand_type).pagesperblock; page++)
|
| 429 | + {
|
| 430 | + pagenum = block * (*ftl_nand_type).pagesperblock + page;
|
| 431 | + if ((nand_read_page(bank, pagenum, ftl_buffer,
|
| 432 | + &ftl_sparebuffer, 1, 0) & 0x11F) != 0)
|
| 433 | + continue;
|
| 434 | + if (memcmp(ftl_buffer, "DEVICEINFOSIGN\0", 0x10) == 0)
|
| 435 | + return pagenum;
|
| 436 | + }
|
| 437 | + }
|
| 438 | + return 0;
|
| 439 | +}
|
| 440 | +
|
| 441 | +
|
| 442 | +/* Checks if all banks have proper device info pages */
|
| 443 | +uint32_t ftl_has_devinfo(void)
|
| 444 | +{
|
| 445 | + uint32_t i;
|
| 446 | + for (i = 0; i < ftl_banks; i++) if (ftl_find_devinfo(i) == 0) return 0;
|
| 447 | + return 1;
|
| 448 | +}
|
| 449 | +
|
| 450 | +
|
| 451 | +/* Loads the lowlevel BBT for a bank to the specified buffer.
|
| 452 | + This is based on some cryptic disassembly and not fully understood yet. */
|
| 453 | +uint32_t ftl_load_bbt(uint32_t bank, uint8_t* bbt)
|
| 454 | +{
|
| 455 | + uint32_t i, j;
|
| 456 | + uint32_t pagebase, page = ftl_find_devinfo(bank), page2;
|
| 457 | + uint32_t unk1, unk2, unk3;
|
| 458 | + if (page == 0) return 1;
|
| 459 | + pagebase = page & ~((*ftl_nand_type).pagesperblock - 1);
|
| 460 | + if ((nand_read_page(bank, page, ftl_buffer,
|
| 461 | + (uint32_t*)0, 1, 0) & 0x11F) != 0) return 1;
|
| 462 | + if (memcmp(&ftl_buffer[0x18], "BBT", 4) != 0) return 1;
|
| 463 | + unk1 = ((uint16_t*)ftl_buffer)[0x10];
|
| 464 | + unk2 = ((uint16_t*)ftl_buffer)[0x11];
|
| 465 | + unk3 = ((uint16_t*)ftl_buffer)[((uint32_t*)ftl_buffer)[4] * 0xC + 10]
|
| 466 | + + ((uint16_t*)ftl_buffer)[((uint32_t*)ftl_buffer)[4] * 0xC + 11];
|
| 467 | + for (i = 0; i < unk1; i++)
|
| 468 | + {
|
| 469 | + for (j = 0; ; j++)
|
| 470 | + {
|
| 471 | + page2 = unk2 + i + unk3 * j;
|
| 472 | + if (page2 >= (uint32_t)((*ftl_nand_type).pagesperblock - 8))
|
| 473 | + break;
|
| 474 | + if ((nand_read_page(bank, pagebase + page2, ftl_buffer,
|
| 475 | + (void*)0, 1, 0) & 0x11F) == 0)
|
| 476 | + {
|
| 477 | + memcpy(bbt, ftl_buffer, 0x410);
|
| 478 | + return 0;
|
| 479 | + }
|
| 480 | + }
|
| 481 | + }
|
| 482 | + return 1;
|
| 483 | +}
|
| 484 | +
|
| 485 | +
|
| 486 | +/* Calculates the checksums for the VFL context page of the specified bank */
|
| 487 | +void ftl_vfl_calculate_checksum(uint32_t bank,
|
| 488 | + uint32_t* checksum1, uint32_t* checksum2)
|
| 489 | +{
|
| 490 | + uint32_t i;
|
| 491 | + *checksum1 = 0xAABBCCDD;
|
| 492 | + *checksum2 = 0xAABBCCDD;
|
| 493 | + for (i = 0; i < 0x1FE; i++)
|
| 494 | + {
|
| 495 | + *checksum1 += ((uint32_t*)(&ftl_vfl_cxt[bank]))[i];
|
| 496 | + *checksum2 ^= ((uint32_t*)(&ftl_vfl_cxt[bank]))[i];
|
| 497 | + }
|
| 498 | +}
|
| 499 | +
|
| 500 | +
|
| 501 | +/* Checks if the checksums of the VFL context
|
| 502 | + of the specified bank are correct */
|
| 503 | +uint32_t ftl_vfl_verify_checksum(uint32_t bank)
|
| 504 | +{
|
| 505 | + uint32_t checksum1, checksum2;
|
| 506 | + ftl_vfl_calculate_checksum(bank, &checksum1, &checksum2);
|
| 507 | + if (checksum1 == ftl_vfl_cxt[bank].checksum1) return 0;
|
| 508 | + /* The following line is pretty obviously a bug in Whimory,
|
| 509 | + but we do it the same way for compatibility. */
|
| 510 | + if (checksum2 != ftl_vfl_cxt[bank].checksum2) return 0;
|
| 511 | + return 1;
|
| 512 | +}
|
| 513 | +
|
| 514 | +
|
| 515 | +#ifndef FTL_READONLY
|
| 516 | +/* Updates the checksums of the VFL context of the specified bank */
|
| 517 | +void ftl_vfl_update_checksum(uint32_t bank)
|
| 518 | +{
|
| 519 | + ftl_vfl_calculate_checksum(bank, &ftl_vfl_cxt[bank].checksum1,
|
| 520 | + &ftl_vfl_cxt[bank].checksum2);
|
| 521 | +}
|
| 522 | +#endif
|
| 523 | +
|
| 524 | +
|
| 525 | +#ifndef FTL_READONLY
|
| 526 | +/* Writes 8 copies of the VFL context of the specified bank to flash,
|
| 527 | + and succeeds if at least 4 can be read back properly. */
|
| 528 | +uint32_t ftl_vfl_store_cxt(uint32_t bank)
|
| 529 | +{
|
| 530 | + uint32_t i;
|
| 531 | + ftl_vfl_cxt[bank].updatecount--;
|
| 532 | + ftl_vfl_cxt[bank].usn = ++ftl_vfl_usn;
|
| 533 | + ftl_vfl_cxt[bank].nextcxtpage += 8;
|
| 534 | + ftl_vfl_update_checksum(bank);
|
| 535 | + memset(&ftl_sparebuffer, 0xFF, 0x40);
|
| 536 | + ftl_sparebuffer.meta.usn = ftl_vfl_cxt[bank].updatecount;
|
| 537 | + ftl_sparebuffer.meta.field_8 = 0;
|
| 538 | + ftl_sparebuffer.meta.type = 0x80;
|
| 539 | + for (i = 1; i <= 8; i++)
|
| 540 | + {
|
| 541 | + uint32_t index = ftl_vfl_cxt[bank].activecxtblock;
|
| 542 | + uint32_t block = ftl_vfl_cxt[bank].vflcxtblocks[index];
|
| 543 | + uint32_t page = block * (*ftl_nand_type).pagesperblock;
|
| 544 | + page += ftl_vfl_cxt[bank].nextcxtpage - i;
|
| 545 | + nand_write_page(bank, page, &ftl_vfl_cxt[bank], &ftl_sparebuffer, 1);
|
| 546 | + }
|
| 547 | + uint32_t good = 0;
|
| 548 | + for (i = 0; i < 8; i++)
|
| 549 | + {
|
| 550 | + uint32_t index = ftl_vfl_cxt[bank].activecxtblock;
|
| 551 | + uint32_t block = ftl_vfl_cxt[bank].vflcxtblocks[index];
|
| 552 | + uint32_t page = block * (*ftl_nand_type).pagesperblock;
|
| 553 | + page += ftl_vfl_cxt[bank].nextcxtpage - i;
|
| 554 | + if ((nand_read_page(bank, page, ftl_buffer,
|
| 555 | + &ftl_sparebuffer, 1, 0) & 0x11F) != 0)
|
| 556 | + continue;
|
| 557 | + if (memcmp(ftl_buffer, &ftl_vfl_cxt[bank], 0x7AC) != 0)
|
| 558 | + continue;
|
| 559 | + if (ftl_sparebuffer.meta.usn != ftl_vfl_cxt[bank].updatecount)
|
| 560 | + continue;
|
| 561 | + if (ftl_sparebuffer.meta.field_8 == 0
|
| 562 | + && ftl_sparebuffer.meta.type == 0x80) good++;
|
| 563 | + }
|
| 564 | + return good > 3 ? 0 : 1;
|
| 565 | +}
|
| 566 | +#endif
|
| 567 | +
|
| 568 | +
|
| 569 | +#ifndef FTL_READONLY
|
| 570 | +/* Commits the VFL context of the specified bank to flash,
|
| 571 | + retries until it works or all available pages have been tried */
|
| 572 | +uint32_t ftl_vfl_commit_cxt(uint32_t bank)
|
| 573 | +{
|
| 574 | + if (ftl_vfl_cxt[bank].nextcxtpage + 8 <= (*ftl_nand_type).pagesperblock)
|
| 575 | + if (ftl_vfl_store_cxt(bank) == 0) return 0;
|
| 576 | + uint32_t current = ftl_vfl_cxt[bank].activecxtblock;
|
| 577 | + uint32_t i = current, j;
|
| 578 | + while (1)
|
| 579 | + {
|
| 580 | + i = (i + 1) & 3;
|
| 581 | + if (i == current) break;
|
| 582 | + if (ftl_vfl_cxt[bank].vflcxtblocks[i] == 0xFFFF) continue;
|
| 583 | + for (j = 0; j < 4; j++)
|
| 584 | + if (nand_block_erase(bank, ftl_vfl_cxt[bank].vflcxtblocks[i]
|
| 585 | + * (*ftl_nand_type).pagesperblock) == 0)
|
| 586 | + break;
|
| 587 | + if (j == 4) continue;
|
| 588 | + ftl_vfl_cxt[bank].activecxtblock = i;
|
| 589 | + ftl_vfl_cxt[bank].nextcxtpage = 0;
|
| 590 | + if (ftl_vfl_store_cxt(bank) == 0) return 0;
|
| 591 | + }
|
| 592 | + return 1;
|
| 593 | +}
|
| 594 | +#endif
|
| 595 | +
|
| 596 | +
|
| 597 | +/* Returns a pointer to the most recently updated VFL context,
|
| 598 | + used to find out the current FTL context vBlock numbers
|
| 599 | + (planetbeing's "maxthing") */
|
| 600 | +struct ftl_vfl_cxt_type* ftl_vfl_get_newest_cxt(void)
|
| 601 | +{
|
| 602 | + uint32_t i, maxusn;
|
| 603 | + struct ftl_vfl_cxt_type* cxt = (struct ftl_vfl_cxt_type*)0;
|
| 604 | + maxusn = 0;
|
| 605 | + for (i = 0; i < ftl_banks; i++)
|
| 606 | + if (ftl_vfl_cxt[i].usn >= maxusn)
|
| 607 | + {
|
| 608 | + cxt = &ftl_vfl_cxt[i];
|
| 609 | + maxusn = ftl_vfl_cxt[i].usn;
|
| 610 | + }
|
| 611 | + return cxt;
|
| 612 | +}
|
| 613 | +
|
| 614 | +
|
| 615 | +/* Checks if the specified pBlock is marked bad in the supplied lowlevel BBT.
|
| 616 | + Only used while mounting the VFL. */
|
| 617 | +uint32_t ftl_is_good_block(uint8_t* bbt, uint32_t block)
|
| 618 | +{
|
| 619 | + if ((bbt[block >> 3] & (1 << (block & 7))) == 0) return 0;
|
| 620 | + else return 1;
|
| 621 | +}
|
| 622 | +
|
| 623 | +
|
| 624 | +/* Checks if the specified vBlock could be remapped */
|
| 625 | +uint32_t ftl_vfl_is_good_block(uint32_t bank, uint32_t block)
|
| 626 | +{
|
| 627 | + uint8_t bbtentry = ftl_vfl_cxt[bank].bbt[block >> 6];
|
| 628 | + if ((bbtentry & (1 << ((7 - (block >> 3)) & 7))) == 0) return 0;
|
| 629 | + else return 1;
|
| 630 | +}
|
| 631 | +
|
| 632 | +
|
| 633 | +#ifndef FTL_READONLY
|
| 634 | +/* Sets or unsets the bad bit of the specified vBlock
|
| 635 | + in the specified bank's VFL context */
|
| 636 | +void ftl_vfl_set_good_block(uint32_t bank, uint32_t block, uint32_t isgood)
|
| 637 | +{
|
| 638 | + uint8_t bit = (1 << ((7 - (block >> 3)) & 7));
|
| 639 | + if (isgood == 1) ftl_vfl_cxt[bank].bbt[block >> 6] |= bit;
|
| 640 | + else ftl_vfl_cxt[bank].bbt[block >> 6] &= ~bit;
|
| 641 | +}
|
| 642 | +#endif
|
| 643 | +
|
| 644 | +
|
| 645 | +/* Tries to read a VFL context from the specified bank, pBlock and page */
|
| 646 | +uint32_t ftl_vfl_read_page(uint32_t bank, uint32_t block,
|
| 647 | + uint32_t startpage, void* databuffer,
|
| 648 | + union ftl_spare_data_type* sparebuffer)
|
| 649 | +{
|
| 650 | + uint32_t i;
|
| 651 | + for (i = 0; i < 8; i++)
|
| 652 | + {
|
| 653 | + uint32_t page = block * (*ftl_nand_type).pagesperblock
|
| 654 | + + startpage + i;
|
| 655 | + if ((nand_read_page(bank, page, databuffer,
|
| 656 | + sparebuffer, 1, 1) & 0x11F) == 0)
|
| 657 | + if ((*sparebuffer).meta.field_8 == 0
|
| 658 | + && (*sparebuffer).meta.type == 0x80)
|
| 659 | + return 0;
|
| 660 | + }
|
| 661 | + return 1;
|
| 662 | +}
|
| 663 | +
|
| 664 | +
|
| 665 | +/* Translates a bank and vBlock to a pBlock, following remaps */
|
| 666 | +uint32_t ftl_vfl_get_physical_block(uint32_t bank, uint32_t block)
|
| 667 | +{
|
| 668 | + if (ftl_vfl_is_good_block(bank, block) == 1) return block;
|
| 669 | +
|
| 670 | + uint32_t spareindex;
|
| 671 | + uint32_t spareused = ftl_vfl_cxt[bank].spareused;
|
| 672 | + for (spareindex = 0; spareindex < spareused; spareindex++)
|
| 673 | + if (ftl_vfl_cxt[bank].remaptable[spareindex] == block)
|
| 674 | + return ftl_vfl_cxt[bank].firstspare + spareindex;
|
| 675 | + return block;
|
| 676 | +}
|
| 677 | +
|
| 678 | +
|
| 679 | +#ifndef FTL_READONLY
|
| 680 | +/* Checks if remapping is scheduled for the specified bank and vBlock */
|
| 681 | +uint32_t ftl_vfl_check_remap_scheduled(uint32_t bank, uint32_t block)
|
| 682 | +{
|
| 683 | + uint32_t i;
|
| 684 | + for (i = 0x333; i > 0 && i > ftl_vfl_cxt[bank].scheduledstart; i--)
|
| 685 | + if (ftl_vfl_cxt[bank].remaptable[i] == block) return 1;
|
| 686 | + return 0;
|
| 687 | +}
|
| 688 | +#endif
|
| 689 | +
|
| 690 | +
|
| 691 | +#ifndef FTL_READONLY
|
| 692 | +/* Schedules remapping for the specified bank and vBlock */
|
| 693 | +void ftl_vfl_schedule_block_for_remap(uint32_t bank, uint32_t block)
|
| 694 | +{
|
| 695 | + if (ftl_vfl_check_remap_scheduled(bank, block) == 1) return;
|
| 696 | + if (ftl_vfl_cxt[bank].scheduledstart == ftl_vfl_cxt[bank].spareused)
|
| 697 | + return;
|
| 698 | + ftl_vfl_cxt[bank].remaptable[--ftl_vfl_cxt[bank].scheduledstart] = block;
|
| 699 | + ftl_vfl_commit_cxt(bank);
|
| 700 | +}
|
| 701 | +#endif
|
| 702 | +
|
| 703 | +
|
| 704 | +#ifndef FTL_READONLY
|
| 705 | +/* Removes the specified bank and vBlock combination
|
| 706 | + from the remap scheduled list */
|
| 707 | +void ftl_vfl_mark_remap_done(uint32_t bank, uint32_t block)
|
| 708 | +{
|
| 709 | + uint32_t i;
|
| 710 | + uint32_t start = ftl_vfl_cxt[bank].scheduledstart;
|
| 711 | + uint32_t lastscheduled = ftl_vfl_cxt[bank].remaptable[start];
|
| 712 | + for (i = 0x333; i > 0 && i > start; i--)
|
| 713 | + if (ftl_vfl_cxt[bank].remaptable[i] == block)
|
| 714 | + {
|
| 715 | + if (i != start && i != 0x333)
|
| 716 | + ftl_vfl_cxt[bank].remaptable[i] = lastscheduled;
|
| 717 | + ftl_vfl_cxt[bank].scheduledstart++;
|
| 718 | + return;
|
| 719 | + }
|
| 720 | +}
|
| 721 | +#endif
|
| 722 | +
|
| 723 | +
|
| 724 | +#ifndef FTL_READONLY
|
| 725 | +/* Logs that there is trouble for the specified vBlock on the specified bank.
|
| 726 | + The vBlock will be scheduled for remap
|
| 727 | + if there is too much trouble with it. */
|
| 728 | +void ftl_vfl_log_trouble(uint32_t bank, uint32_t vblock)
|
| 729 | +{
|
| 730 | + uint32_t i;
|
| 731 | + for (i = 0; i < 5; i++)
|
| 732 | + if (ftl_troublelog[i].block == vblock
|
| 733 | + && ftl_troublelog[i].bank == bank)
|
| 734 | + {
|
| 735 | + ftl_troublelog[i].errors += 3;
|
| 736 | + if (ftl_troublelog[i].errors > 5)
|
| 737 | + {
|
| 738 | + ftl_vfl_schedule_block_for_remap(bank, vblock);
|
| 739 | + ftl_troublelog[i].block = 0xFFFF;
|
| 740 | + }
|
| 741 | + return;
|
| 742 | + }
|
| 743 | + for (i = 0; i < 5; i++)
|
| 744 | + if (ftl_troublelog[i].block == 0xFFFF)
|
| 745 | + {
|
| 746 | + ftl_troublelog[i].block = vblock;
|
| 747 | + ftl_troublelog[i].bank = bank;
|
| 748 | + ftl_troublelog[i].errors = 3;
|
| 749 | + return;
|
| 750 | + }
|
| 751 | +}
|
| 752 | +#endif
|
| 753 | +
|
| 754 | +
|
| 755 | +#ifndef FTL_READONLY
|
| 756 | +/* Logs a successful erase for the specified vBlock on the specified bank */
|
| 757 | +void ftl_vfl_log_success(uint32_t bank, uint32_t vblock)
|
| 758 | +{
|
| 759 | + uint32_t i;
|
| 760 | + for (i = 0; i < 5; i++)
|
| 761 | + if (ftl_troublelog[i].block == vblock
|
| 762 | + && ftl_troublelog[i].bank == bank)
|
| 763 | + {
|
| 764 | + if (--ftl_troublelog[i].errors == 0)
|
| 765 | + ftl_troublelog[i].block = 0xFFFF;
|
| 766 | + return;
|
| 767 | + }
|
| 768 | +}
|
| 769 | +#endif
|
| 770 | +
|
| 771 | +
|
| 772 | +#ifndef FTL_READONLY
|
| 773 | +/* Tries to remap the specified vBlock on the specified bank,
|
| 774 | + not caring about data in there.
|
| 775 | + If it worked, it will return the new pBlock number,
|
| 776 | + if not (no more spare blocks available), it will return zero. */
|
| 777 | +uint32_t ftl_vfl_remap_block(uint32_t bank, uint32_t block)
|
| 778 | +{
|
| 779 | + uint32_t i;
|
| 780 | + uint32_t newblock = 0, newidx;
|
| 781 | + if (bank >= ftl_banks || block >= (*ftl_nand_type).blocks) return 0;
|
| 782 | + for (i = 0; i < ftl_vfl_cxt[bank].sparecount; i++)
|
| 783 | + if (ftl_vfl_cxt[bank].remaptable[i] == 0)
|
| 784 | + {
|
| 785 | + newblock = ftl_vfl_cxt[bank].firstspare + i;
|
| 786 | + newidx = i;
|
| 787 | + break;
|
| 788 | + }
|
| 789 | + if (newblock == 0) return 0;
|
| 790 | + for (i = 0; i < 9; i++)
|
| 791 | + if (nand_block_erase(bank,
|
| 792 | + newblock * (*ftl_nand_type).pagesperblock) == 0)
|
| 793 | + break;
|
| 794 | + for (i = 0; i < newidx; i++)
|
| 795 | + if (ftl_vfl_cxt[bank].remaptable[i] == block)
|
| 796 | + ftl_vfl_cxt[bank].remaptable[i] = 0xFFFF;
|
| 797 | + ftl_vfl_cxt[bank].remaptable[newidx] = block;
|
| 798 | + ftl_vfl_cxt[bank].spareused++;
|
| 799 | + ftl_vfl_set_good_block(bank, block, 0);
|
| 800 | + return newblock;
|
| 801 | +}
|
| 802 | +#endif
|
| 803 | +
|
| 804 | +
|
| 805 | +// Reads the specified vPage, dealing with all kinds of trouble
|
| 806 | +uint32_t ftl_vfl_read(uint32_t vpage, void* buffer, void* sparebuffer,
|
| 807 | + uint32_t checkempty, uint32_t remaponfail)
|
| 808 | +{
|
| 809 | + uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
|
| 810 | + uint32_t syshyperblocks = (*ftl_nand_type).blocks
|
| 811 | + - (*ftl_nand_type).userblocks - 0x17;
|
| 812 | + uint32_t abspage = vpage + ppb * syshyperblocks;
|
| 813 | + if (abspage >= (*ftl_nand_type).blocks * ppb || abspage < ppb)
|
| 814 | + {
|
| 815 | + return 4;
|
| 816 | + }
|
| 817 | +
|
| 818 | + uint32_t bank = abspage % ftl_banks;
|
| 819 | + uint32_t block = abspage / ((*ftl_nand_type).pagesperblock * ftl_banks);
|
| 820 | + uint32_t page = (abspage / ftl_banks) % (*ftl_nand_type).pagesperblock;
|
| 821 | + uint32_t physblock = ftl_vfl_get_physical_block(bank, block);
|
| 822 | + uint32_t physpage = physblock * (*ftl_nand_type).pagesperblock + page;
|
| 823 | +
|
| 824 | + uint32_t ret = nand_read_page(bank, physpage, buffer,
|
| 825 | + sparebuffer, 1, checkempty);
|
| 826 | +
|
| 827 | + if ((ret & 0x11D) != 0 && (ret & 2) == 0)
|
| 828 | + {
|
| 829 | + nand_reset(bank);
|
| 830 | + ret = nand_read_page(bank, physpage, buffer,
|
| 831 | + sparebuffer, 1, checkempty);
|
| 832 | +#ifdef FTL_READONLY
|
| 833 | + (void)remaponfail;
|
| 834 | +#else
|
| 835 | + if (remaponfail == 1 &&(ret & 0x11D) != 0 && (ret & 2) == 0)
|
| 836 | + {
|
| 837 | + ftl_vfl_schedule_block_for_remap(bank, block);
|
| 838 | + }
|
| 839 | +#endif
|
| 840 | + return ret;
|
| 841 | + }
|
| 842 | +
|
| 843 | + return ret;
|
| 844 | +}
|
| 845 | +
|
| 846 | +
|
| 847 | +#ifndef FTL_READONLY
|
| 848 | +/* Writes the specified vPage, dealing with all kinds of trouble */
|
| 849 | +uint32_t ftl_vfl_write(uint32_t vpage, void* buffer, void* sparebuffer)
|
| 850 | +{
|
| 851 | + uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
|
| 852 | + uint32_t syshyperblocks = (*ftl_nand_type).blocks
|
| 853 | + - (*ftl_nand_type).userblocks - 0x17;
|
| 854 | + uint32_t abspage = vpage + ppb * syshyperblocks;
|
| 855 | + if (abspage >= (*ftl_nand_type).blocks * ppb || abspage < ppb)
|
| 856 | + {
|
| 857 | + return 4;
|
| 858 | + }
|
| 859 | +
|
| 860 | + uint32_t bank = abspage % ftl_banks;
|
| 861 | + uint32_t block = abspage / ((*ftl_nand_type).pagesperblock * ftl_banks);
|
| 862 | + uint32_t page = (abspage / ftl_banks) % (*ftl_nand_type).pagesperblock;
|
| 863 | + uint32_t physblock = ftl_vfl_get_physical_block(bank, block);
|
| 864 | + uint32_t physpage = physblock * (*ftl_nand_type).pagesperblock + page;
|
| 865 | +
|
| 866 | + if (nand_write_page(bank, physpage, buffer, sparebuffer, 1) == 0)
|
| 867 | + return 0;
|
| 868 | + if ((nand_read_page(bank, physpage, ftl_buffer,
|
| 869 | + &ftl_sparebuffer, 1, 1) & 0x11F) == 0)
|
| 870 | + return 0;
|
| 871 | + ftl_vfl_log_trouble(bank, block);
|
| 872 | + return 1;
|
| 873 | +}
|
| 874 | +#endif
|
| 875 | +
|
| 876 | +
|
| 877 | +/* Mounts the VFL on all banks */
|
| 878 | +uint32_t ftl_vfl_open(void)
|
| 879 | +{
|
| 880 | + uint32_t i, j, k;
|
| 881 | + uint32_t minusn, vflcxtidx, last;
|
| 882 | + struct ftl_vfl_cxt_type* cxt;
|
| 883 | + uint16_t vflcxtblock[4];
|
| 884 | +#ifndef FTL_READONLY
|
| 885 | + ftl_vfl_usn = 0;
|
| 886 | +#else
|
| 887 | + /* Temporary BBT buffer if we're readonly,
|
| 888 | + as we won't need it again after mounting */
|
| 889 | + uint8_t bbt[0x410];
|
| 890 | +#endif
|
| 891 | +
|
| 892 | + uint32_t syshyperblocks = (*ftl_nand_type).blocks
|
| 893 | + - (*ftl_nand_type).userblocks - 0x18;
|
| 894 | +
|
| 895 | + for (i = 0; i < ftl_banks; i++)
|
| 896 | +#ifndef FTL_READONLY
|
| 897 | + if (ftl_load_bbt(i, ftl_bbt[i]) == 0)
|
| 898 | +#else
|
| 899 | + if (ftl_load_bbt(i, bbt) == 0)
|
| 900 | +#endif
|
| 901 | + {
|
| 902 | + for (j = 1; j <= syshyperblocks; j++)
|
| 903 | +#ifndef FTL_READONLY
|
| 904 | + if (ftl_is_good_block(ftl_bbt[i], j) != 0)
|
| 905 | +#else
|
| 906 | + if (ftl_is_good_block(bbt, j) != 0)
|
| 907 | +#endif
|
| 908 | + if (ftl_vfl_read_page(i, j, 0, ftl_buffer,
|
| 909 | + &ftl_sparebuffer) == 0)
|
| 910 | + {
|
| 911 | + struct ftl_vfl_cxt_type* cxt;
|
| 912 | + cxt = (struct ftl_vfl_cxt_type*)ftl_buffer;
|
| 913 | + memcpy(vflcxtblock, &(*cxt).vflcxtblocks, 8);
|
| 914 | + minusn = 0xFFFFFFFF;
|
| 915 | + vflcxtidx = 4;
|
| 916 | + for (k = 0; k < 4; k++)
|
| 917 | + if (vflcxtblock[k] != 0xFFFF)
|
| 918 | + if (ftl_vfl_read_page(i, vflcxtblock[k], 0,
|
| 919 | + ftl_buffer,
|
| 920 | + &ftl_sparebuffer) == 0)
|
| 921 | + if (ftl_sparebuffer.meta.usn > 0
|
| 922 | + && ftl_sparebuffer.meta.usn <= minusn)
|
| 923 | + {
|
| 924 | + minusn = ftl_sparebuffer.meta.usn;
|
| 925 | + vflcxtidx = k;
|
| 926 | + }
|
| 927 | + if (vflcxtidx == 4) return 1;
|
| 928 | + last = 0;
|
| 929 | + uint32_t max = (*ftl_nand_type).pagesperblock;
|
| 930 | + for (k = 8; k < max; k += 8)
|
| 931 | + {
|
| 932 | + if (ftl_vfl_read_page(i, vflcxtblock[vflcxtidx],
|
| 933 | + k, ftl_buffer,
|
| 934 | + &ftl_sparebuffer) != 0)
|
| 935 | + break;
|
| 936 | + last = k;
|
| 937 | + }
|
| 938 | + if (ftl_vfl_read_page(i, vflcxtblock[vflcxtidx],
|
| 939 | + last, ftl_buffer,
|
| 940 | + &ftl_sparebuffer) != 0)
|
| 941 | + return 1;
|
| 942 | + memcpy(&ftl_vfl_cxt[i], ftl_buffer, 0x800);
|
| 943 | + if (ftl_vfl_verify_checksum(i) != 0) return 1;
|
| 944 | +#ifndef FTL_READONLY
|
| 945 | + if (ftl_vfl_usn < ftl_vfl_cxt[i].usn)
|
| 946 | + ftl_vfl_usn = ftl_vfl_cxt[i].usn;
|
| 947 | +#endif
|
| 948 | + break;
|
| 949 | + }
|
| 950 | + }
|
| 951 | + else
|
| 952 | + {
|
| 953 | + return 1;
|
| 954 | + }
|
| 955 | + cxt = ftl_vfl_get_newest_cxt();
|
| 956 | + for (i = 0; i < ftl_banks; i++)
|
| 957 | + memcpy(ftl_vfl_cxt[i].ftlctrlblocks, (*cxt).ftlctrlblocks, 6);
|
| 958 | + return 0;
|
| 959 | +}
|
| 960 | +
|
| 961 | +
|
| 962 | +/* Mounts the actual FTL */
|
| 963 | +uint32_t ftl_open(void)
|
| 964 | +{
|
| 965 | + uint32_t i;
|
| 966 | + uint32_t ret;
|
| 967 | + uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
|
| 968 | + struct ftl_vfl_cxt_type* cxt = ftl_vfl_get_newest_cxt();
|
| 969 | +
|
| 970 | + uint32_t ftlcxtblock = 0xffffffff;
|
| 971 | + uint32_t minlpn = 0xffffffff;
|
| 972 | + for (i = 0; i < 3; i++)
|
| 973 | + {
|
| 974 | + ret = ftl_vfl_read(ppb * (*cxt).ftlctrlblocks[i],
|
| 975 | + ftl_buffer, &ftl_sparebuffer, 1, 0);
|
| 976 | + if ((ret &= 0x11F) != 0) continue;
|
| 977 | + if (ftl_sparebuffer.user.type - 0x43 > 4) continue;
|
| 978 | + if (ftlcxtblock != 0xffffffff && ftl_sparebuffer.user.lpn >= minlpn)
|
| 979 | + continue;
|
| 980 | + minlpn = ftl_sparebuffer.user.lpn;
|
| 981 | + ftlcxtblock = (*cxt).ftlctrlblocks[i];
|
| 982 | + }
|
| 983 | +
|
| 984 | + if (ftlcxtblock == 0xffffffff) return 1;
|
| 985 | +
|
| 986 | + uint32_t ftlcxtfound = 0;
|
| 987 | + for (i = (*ftl_nand_type).pagesperblock * ftl_banks - 1; i > 0; i--)
|
| 988 | + {
|
| 989 | + ret = ftl_vfl_read(ppb * ftlcxtblock + i,
|
| 990 | + ftl_buffer, &ftl_sparebuffer, 1, 0);
|
| 991 | + if ((ret & 0x11F) != 0) continue;
|
| 992 | + else if (ftl_sparebuffer.user.type == 0x43)
|
| 993 | + {
|
| 994 | + memcpy(&ftl_cxt, ftl_buffer, 0x28C);
|
| 995 | + ftlcxtfound = 1;
|
| 996 | + break;
|
| 997 | + }
|
| 998 | + else
|
| 999 | + {
|
| 1000 | + // This will trip if there was an unclean unmount before.
|
| 1001 | +#ifndef FTL_FORCEMOUNT
|
| 1002 | + break;
|
| 1003 | +#endif
|
| 1004 | + }
|
| 1005 | + }
|
| 1006 | +
|
| 1007 | + if (ftlcxtfound == 0) return 1;
|
| 1008 | +
|
| 1009 | + uint32_t pagestoread = (*ftl_nand_type).userblocks >> 10;
|
| 1010 | + if (((*ftl_nand_type).userblocks & 0x1FF) != 0) pagestoread++;
|
| 1011 | +
|
| 1012 | + for (i = 0; i < pagestoread; i++)
|
| 1013 | + {
|
| 1014 | + if ((ftl_vfl_read(ftl_cxt.ftl_map_pages[i],
|
| 1015 | + ftl_buffer, &ftl_sparebuffer, 1, 1) & 0x11F) != 0)
|
| 1016 | + return 1;
|
| 1017 | +
|
| 1018 | + uint32_t toread = 2048;
|
| 1019 | + if (toread > ((*ftl_nand_type).userblocks << 1) - (i << 11))
|
| 1020 | + toread = ((*ftl_nand_type).userblocks << 1) - (i << 11);
|
| 1021 | +
|
| 1022 | + memcpy(&ftl_map[i << 10], ftl_buffer, toread);
|
| 1023 | + }
|
| 1024 | +
|
| 1025 | +#ifndef FTL_READONLY
|
| 1026 | + pagestoread = ((*ftl_nand_type).userblocks + 23) >> 10;
|
| 1027 | + if ((((*ftl_nand_type).userblocks + 23) & 0x1FF) != 0) pagestoread++;
|
| 1028 | +
|
| 1029 | + for (i = 0; i < pagestoread; i++)
|
| 1030 | + {
|
| 1031 | + if ((ftl_vfl_read(ftl_cxt.ftl_erasectr_pages[i],
|
| 1032 | + ftl_buffer, &ftl_sparebuffer, 1, 1) & 0x11F) != 0)
|
| 1033 | + return 1;
|
| 1034 | +
|
| 1035 | + uint32_t toread = 2048;
|
| 1036 | + if (toread > (((*ftl_nand_type).userblocks + 23) << 1) - (i << 11))
|
| 1037 | + toread = (((*ftl_nand_type).userblocks + 23) << 1) - (i << 11);
|
| 1038 | +
|
| 1039 | + memcpy(&ftl_erasectr[i << 10], ftl_buffer, toread);
|
| 1040 | + }
|
| 1041 | +
|
| 1042 | + for (i = 0; i < 0x11; i++)
|
| 1043 | + {
|
| 1044 | + ftl_log[i].scatteredvblock = 0xFFFF;
|
| 1045 | + ftl_log[i].logicalvblock = 0xFFFF;
|
| 1046 | + ftl_log[i].pageoffsets = ftl_offsets[i];
|
| 1047 | + }
|
| 1048 | +
|
| 1049 | + memset(ftl_troublelog, 0xFF, 20);
|
| 1050 | + memset(ftl_erasectr_dirt, 0, 8);
|
| 1051 | +#endif
|
| 1052 | +
|
| 1053 | + return 0;
|
| 1054 | +}
|
| 1055 | +
|
| 1056 | +
|
| 1057 | +#ifndef FTL_READONLY
|
| 1058 | +/* Returns a pointer to the ftl_log entry for the specified vBlock,
|
| 1059 | + or null, if there is none */
|
| 1060 | +struct ftl_log_type* ftl_get_log_entry(uint32_t block)
|
| 1061 | +{
|
| 1062 | + uint32_t i;
|
| 1063 | + for (i = 0; i < 0x11; i++)
|
| 1064 | + {
|
| 1065 | + if (ftl_log[i].scatteredvblock == 0xFFFF) continue;
|
| 1066 | + if (ftl_log[i].logicalvblock == block) return &ftl_log[i];
|
| 1067 | + }
|
| 1068 | + return (struct ftl_log_type*)0;
|
| 1069 | +}
|
| 1070 | +#endif
|
| 1071 | +
|
| 1072 | +/* Exposed function: Read highlevel sectors */
|
| 1073 | +uint32_t storage_read(uint32_t sector, uint32_t count, void* buffer)
|
| 1074 | +{
|
| 1075 | + uint32_t i;
|
| 1076 | + uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
|
| 1077 | + uint32_t error = 0;
|
| 1078 | +
|
| 1079 | + if (sector + count > (*ftl_nand_type).userblocks * ppb)
|
| 1080 | + return 1;
|
| 1081 | + if (count == 0) return 0;
|
| 1082 | +
|
| 1083 | + for (i = 0; i < count; i++)
|
| 1084 | + {
|
| 1085 | + uint32_t block = (sector + i) / ppb;
|
| 1086 | + uint32_t page = (sector + i) % ppb;
|
| 1087 | +
|
| 1088 | + uint32_t abspage = ftl_map[block] * ppb + page;
|
| 1089 | +#ifndef FTL_READONLY
|
| 1090 | + struct ftl_log_type* logentry = ftl_get_log_entry(block);
|
| 1091 | + if (logentry != (struct ftl_log_type*)0)
|
| 1092 | + {
|
| 1093 | + if ((*logentry).scatteredvblock != 0xFFFF
|
| 1094 | + && (*logentry).pageoffsets[page] != 0xFFFF)
|
| 1095 | + {
|
| 1096 | + abspage = (*logentry).scatteredvblock * ppb
|
| 1097 | + + (*logentry).pageoffsets[page];
|
| 1098 | + }
|
| 1099 | + }
|
| 1100 | +#endif
|
| 1101 | +
|
| 1102 | + uint32_t ret = ftl_vfl_read(abspage, &((uint8_t*)buffer)[i << 11],
|
| 1103 | + &ftl_sparebuffer, 1, 1);
|
| 1104 | + if ((ret & 2) != 0) memset(&((uint8_t*)buffer)[i << 11], 0, 0x800);
|
| 1105 | + else if ((ret & 0x11D) != 0 || ftl_sparebuffer.user.eccmark != 0xFF)
|
| 1106 | + {
|
| 1107 | + error = 1;
|
| 1108 | + memset(&((uint8_t*)buffer)[i << 11], 0, 0x800);
|
| 1109 | + }
|
| 1110 | + }
|
| 1111 | + return error;
|
| 1112 | +}
|
| 1113 | +
|
| 1114 | +
|
| 1115 | +#ifndef FTL_READONLY
|
| 1116 | +/* Performs a vBlock erase, dealing with hardware,
|
| 1117 | + remapping and all kinds of trouble */
|
| 1118 | +uint32_t ftl_erase_block_internal(uint32_t block)
|
| 1119 | +{
|
| 1120 | + uint32_t i, j;
|
| 1121 | + block = block + (*ftl_nand_type).blocks
|
| 1122 | + - (*ftl_nand_type).userblocks - 0x17;
|
| 1123 | + if (block == 0 || block >= (*ftl_nand_type).blocks) return 1;
|
| 1124 | + for (i = 0; i < ftl_banks; i++)
|
| 1125 | + {
|
| 1126 | + if (ftl_vfl_check_remap_scheduled(i, block) == 1)
|
| 1127 | + {
|
| 1128 | + ftl_vfl_remap_block(i, block);
|
| 1129 | + ftl_vfl_mark_remap_done(i, block);
|
| 1130 | + }
|
| 1131 | + ftl_vfl_log_success(i, block);
|
| 1132 | + uint32_t pblock = ftl_vfl_get_physical_block(i, block);
|
| 1133 | + uint32_t rc;
|
| 1134 | + for (j = 0; j < 3; j++)
|
| 1135 | + {
|
| 1136 | + rc = nand_block_erase(i, pblock * (*ftl_nand_type).pagesperblock);
|
| 1137 | + if (rc == 0) break;
|
| 1138 | + }
|
| 1139 | + if (rc != 0)
|
| 1140 | + {
|
| 1141 | + if (pblock != block)
|
| 1142 | + {
|
| 1143 | + uint32_t spareindex = pblock - ftl_vfl_cxt[i].firstspare;
|
| 1144 | + ftl_vfl_cxt[i].remaptable[spareindex] = 0xFFFF;
|
| 1145 | + }
|
| 1146 | + ftl_vfl_cxt[i].field_18++;
|
| 1147 | + if (ftl_vfl_remap_block(i, block) == 0) return 1;
|
| 1148 | + if (ftl_vfl_commit_cxt(i) != 0) return 1;
|
| 1149 | + memset(&ftl_sparebuffer, 0, 0x40);
|
| 1150 | + nand_write_page(i, pblock, &ftl_vfl_cxt[0], &ftl_sparebuffer, 1);
|
| 1151 | + }
|
| 1152 | + }
|
| 1153 | + return 0;
|
| 1154 | +}
|
| 1155 | +#endif
|
| 1156 | +
|
| 1157 | +
|
| 1158 | +#ifndef FTL_READONLY
|
| 1159 | +/* Highlevel vBlock erase, that increments the erase counter for the block */
|
| 1160 | +uint32_t ftl_erase_block(uint32_t block)
|
| 1161 | +{
|
| 1162 | + ftl_erasectr[block]++;
|
| 1163 | + if (ftl_erasectr_dirt[block >> 10] == 100) ftl_cxt.erasedirty = 1;
|
| 1164 | + else ftl_erasectr_dirt[block >> 10]++;
|
| 1165 | + return ftl_erase_block_internal(block);
|
| 1166 | +}
|
| 1167 | +#endif
|
| 1168 | +
|
| 1169 | +
|
| 1170 | +#ifndef FTL_READONLY
|
| 1171 | +/* Allocates a block from the pool,
|
| 1172 | + returning its vBlock number, or 0xFFFFFFFF on error */
|
| 1173 | +uint32_t ftl_allocate_pool_block(void)
|
| 1174 | +{
|
| 1175 | + uint32_t i;
|
| 1176 | + uint32_t erasectr = 0xFFFFFFFF, bestidx = 0xFFFFFFFF, block;
|
| 1177 | + for (i = 0; i < ftl_cxt.freecount; i++)
|
| 1178 | + {
|
| 1179 | + uint32_t idx = ftl_cxt.nextfreeidx + i;
|
| 1180 | + if (idx >= 0x14) idx -= 0x14;
|
| 1181 | + if (!ftl_cxt.blockpool[idx]) continue;
|
| 1182 | + if (ftl_erasectr[ftl_cxt.blockpool[idx]] < erasectr)
|
| 1183 | + {
|
| 1184 | + erasectr = ftl_erasectr[ftl_cxt.blockpool[idx]];
|
| 1185 | + bestidx = idx;
|
| 1186 | + }
|
| 1187 | + }
|
| 1188 | + if (bestidx == 0xFFFFFFFF) return 0xFFFFFFFF;
|
| 1189 | + block = ftl_cxt.blockpool[bestidx];
|
| 1190 | + if (bestidx != ftl_cxt.nextfreeidx)
|
| 1191 | + {
|
| 1192 | + ftl_cxt.blockpool[bestidx] = ftl_cxt.blockpool[ftl_cxt.nextfreeidx];
|
| 1193 | + ftl_cxt.blockpool[ftl_cxt.nextfreeidx] = block;
|
| 1194 | + }
|
| 1195 | + if (block > (uint32_t)(*ftl_nand_type).userblocks + 0x17) return 0xFFFFFFFF;
|
| 1196 | + if (ftl_erase_block(block) != 0) return 0xFFFFFFFF;
|
| 1197 | + if (++ftl_cxt.nextfreeidx == 0x14) ftl_cxt.nextfreeidx = 0;
|
| 1198 | + ftl_cxt.freecount--;
|
| 1199 | + return block;
|
| 1200 | +}
|
| 1201 | +#endif
|
| 1202 | +
|
| 1203 | +
|
| 1204 | +#ifndef FTL_READONLY
|
| 1205 | +/* Releases a vBlock back into the pool */
|
| 1206 | +void ftl_release_pool_block(uint32_t block)
|
| 1207 | +{
|
| 1208 | + uint32_t idx = ftl_cxt.nextfreeidx + ftl_cxt.freecount++;
|
| 1209 | + if (idx >= 0x14) idx -= 0x14;
|
| 1210 | + ftl_cxt.blockpool[idx] = block;
|
| 1211 | +}
|
| 1212 | +#endif
|
| 1213 | +
|
| 1214 | +
|
| 1215 | +#ifndef FTL_READONLY
|
| 1216 | +/* Commits the location of the FTL context blocks
|
| 1217 | + to a semi-randomly chosen VFL context */
|
| 1218 | +uint32_t ftl_store_ctrl_block_list(void)
|
| 1219 | +{
|
| 1220 | + uint32_t i;
|
| 1221 | + for (i = 0; i < ftl_banks; i++)
|
| 1222 | + memcpy(ftl_vfl_cxt[i].ftlctrlblocks, ftl_cxt.ftlctrlblocks, 6);
|
| 1223 | + return ftl_vfl_commit_cxt(ftl_vfl_usn % ftl_banks);
|
| 1224 | +}
|
| 1225 | +#endif
|
| 1226 | +
|
| 1227 | +
|
| 1228 | +#ifndef FTL_READONLY
|
| 1229 | +/* Saves the n-th erase counter page to the flash,
|
| 1230 | + because it is too dirty or needs to be moved. */
|
| 1231 | +uint32_t ftl_save_erasectr_page(uint32_t index)
|
| 1232 | +{
|
| 1233 | + memset(&ftl_sparebuffer, 0xFF, 0x40);
|
| 1234 | + ftl_sparebuffer.meta.usn = ftl_cxt.usn;
|
| 1235 | + ftl_sparebuffer.meta.idx = index;
|
| 1236 | + ftl_sparebuffer.meta.type = 0x46;
|
| 1237 | + if (ftl_vfl_write(ftl_cxt.ftlctrlpage, &ftl_erasectr[index << 10],
|
| 1238 | + &ftl_sparebuffer) != 0)
|
| 1239 | + return 1;
|
| 1240 | + if ((ftl_vfl_read(ftl_cxt.ftlctrlpage, ftl_buffer,
|
| 1241 | + &ftl_sparebuffer, 1, 1) & 0x11F) != 0)
|
| 1242 | + return 1;
|
| 1243 | + if (memcmp(ftl_buffer, &ftl_erasectr[index << 10], 0x800) != 0) return 1;
|
| 1244 | + if (ftl_sparebuffer.meta.type != 0x46) return 1;
|
| 1245 | + if (ftl_sparebuffer.meta.idx != index) return 1;
|
| 1246 | + if (ftl_sparebuffer.meta.usn != ftl_cxt.usn) return 1;
|
| 1247 | + ftl_cxt.ftl_erasectr_pages[index] = ftl_cxt.ftlctrlpage;
|
| 1248 | + ftl_erasectr_dirt[index] = 0;
|
| 1249 | + return 0;
|
| 1250 | +}
|
| 1251 | +#endif
|
| 1252 | +
|
| 1253 | +
|
| 1254 | +#ifndef FTL_READONLY
|
| 1255 | +/* Increments ftl_cxt.ftlctrlpage to the next available FTL context page,
|
| 1256 | + allocating a new context block if neccessary. */
|
| 1257 | +uint32_t ftl_next_ctrl_pool_page(void)
|
| 1258 | +{
|
| 1259 | + uint32_t i;
|
| 1260 | + uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
|
| 1261 | + if (++ftl_cxt.ftlctrlpage % ppb != 0) return 0;
|
| 1262 | + for (i = 0; i < 3; i++)
|
| 1263 | + if ((ftl_cxt.ftlctrlblocks[i] + 1) * ppb == ftl_cxt.ftlctrlpage)
|
| 1264 | + break;
|
| 1265 | + i = (i + 1) % 3;
|
| 1266 | + uint32_t oldblock = ftl_cxt.ftlctrlblocks[i];
|
| 1267 | + uint32_t newblock = ftl_allocate_pool_block();
|
| 1268 | + if (newblock == 0xFFFFFFFF) return 1;
|
| 1269 | + ftl_cxt.ftlctrlblocks[i] = newblock;
|
| 1270 | + ftl_cxt.ftlctrlpage = newblock * ppb;
|
| 1271 | + uint32_t pagestoread = ((*ftl_nand_type).userblocks + 23) >> 10;
|
| 1272 | + if ((((*ftl_nand_type).userblocks + 23) & 0x1FF) != 0) pagestoread++;
|
| 1273 | + for (i = 0; i < pagestoread; i++)
|
| 1274 | + if (oldblock * ppb <= ftl_cxt.ftl_erasectr_pages[i]
|
| 1275 | + && (oldblock + 1) * ppb > ftl_cxt.ftl_erasectr_pages[i])
|
| 1276 | + {
|
| 1277 | + ftl_cxt.usn--;
|
| 1278 | + if (ftl_save_erasectr_page(i) != 0)
|
| 1279 | + {
|
| 1280 | + ftl_cxt.ftlctrlblocks[i] = oldblock;
|
| 1281 | + ftl_cxt.ftlctrlpage = oldblock * (ppb + 1) - 1;
|
| 1282 | + ftl_release_pool_block(newblock);
|
| 1283 | + return 1;
|
| 1284 | + }
|
| 1285 | + ftl_cxt.ftlctrlpage++;
|
| 1286 | + }
|
| 1287 | + ftl_release_pool_block(oldblock);
|
| 1288 | + return ftl_store_ctrl_block_list();
|
| 1289 | +}
|
| 1290 | +#endif
|
| 1291 | +
|
| 1292 | +
|
| 1293 | +#ifndef FTL_READONLY
|
| 1294 | +/* Copies a vPage from one location to another */
|
| 1295 | +uint32_t ftl_copy_page(uint32_t source, uint32_t destination,
|
| 1296 | + uint32_t lpn, uint32_t type)
|
| 1297 | +{
|
| 1298 | + uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
|
| 1299 | + uint32_t rc = ftl_vfl_read(source, ftl_copybuffer,
|
| 1300 | + &ftl_sparebuffer, 1, 1) & 0x11F;
|
| 1301 | + memset(&ftl_sparebuffer, 0xFF, 0x40);
|
| 1302 | + ftl_sparebuffer.user.lpn = lpn;
|
| 1303 | + ftl_sparebuffer.user.usn = ++ftl_cxt.nextblockusn;
|
| 1304 | + ftl_sparebuffer.user.type = 0x40;
|
| 1305 | + if ((rc & 2) != 0) memset(ftl_copybuffer, 0, 0x800);
|
| 1306 | + else if (rc != 0) ftl_sparebuffer.user.eccmark = 0x55;
|
| 1307 | + if (type == 1 && destination % ppb == ppb - 1)
|
| 1308 | + ftl_sparebuffer.user.type = 0x41;
|
| 1309 | + return ftl_vfl_write(destination, ftl_copybuffer, &ftl_sparebuffer);
|
| 1310 | +}
|
| 1311 | +#endif
|
| 1312 | +
|
| 1313 | +
|
| 1314 | +#ifndef FTL_READONLY
|
| 1315 | +/* Copies a pBlock to a vBlock */
|
| 1316 | +uint32_t ftl_copy_block(uint32_t source, uint32_t destination)
|
| 1317 | +{
|
| 1318 | + uint32_t i;
|
| 1319 | + uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
|
| 1320 | + uint32_t error = 0;
|
| 1321 | + ftl_cxt.nextblockusn++;
|
| 1322 | + for (i = 0; i < ppb; i++)
|
| 1323 | + {
|
| 1324 | + uint32_t rc = storage_read(source * ppb + i, 1, ftl_copybuffer);
|
| 1325 | + memset(&ftl_sparebuffer, 0xFF, 0x40);
|
| 1326 | + ftl_sparebuffer.user.lpn = source * ppb + i;
|
| 1327 | + ftl_sparebuffer.user.usn = ftl_cxt.nextblockusn;
|
| 1328 | + ftl_sparebuffer.user.type = 0x40;
|
| 1329 | + if (rc != 0) ftl_sparebuffer.user.eccmark = 0x55;
|
| 1330 | + if (i == ppb - 1) ftl_sparebuffer.user.type = 0x41;
|
| 1331 | + if (ftl_vfl_write(destination * ppb + i,
|
| 1332 | + ftl_copybuffer, &ftl_sparebuffer) != 0)
|
| 1333 | + {
|
| 1334 | + error = 1;
|
| 1335 | + break;
|
| 1336 | + }
|
| 1337 | + }
|
| 1338 | + if (error != 0)
|
| 1339 | + {
|
| 1340 | + ftl_erase_block(destination);
|
| 1341 | + return 1;
|
| 1342 | + }
|
| 1343 | + return 0;
|
| 1344 | +}
|
| 1345 | +#endif
|
| 1346 | +
|
| 1347 | +
|
| 1348 | +#ifndef FTL_READONLY
|
| 1349 | +/* Clears ftl_log.issequential, if something violating that is written. */
|
| 1350 | +void ftl_check_still_sequential(struct ftl_log_type* entry, uint32_t page)
|
| 1351 | +{
|
| 1352 | + if ((*entry).pagesused != (*entry).pagescurrent
|
| 1353 | + || (*entry).pageoffsets[page] != page)
|
| 1354 | + (*entry).issequential = 0;
|
| 1355 | +}
|
| 1356 | +#endif
|
| 1357 | +
|
| 1358 | +
|
| 1359 | +#ifndef FTL_READONLY
|
| 1360 | +/* Copies all pages that are currently used from the scattered page block in
|
| 1361 | + use by the supplied ftl_log entry to a newly-allocated one, and releases
|
| 1362 | + the old one.
|
| 1363 | + In other words: It kicks the pages containing old garbage out of it to make
|
| 1364 | + space again. This is usually done when a scattered page block is being
|
| 1365 | + removed because it is full, but less than half of the pages in there are
|
| 1366 | + still in use and rest is just filled with old crap. */
|
| 1367 | +uint32_t ftl_compact_scattered(struct ftl_log_type* entry)
|
| 1368 | +{
|
| 1369 | + uint32_t i, j;
|
| 1370 | + uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
|
| 1371 | + uint32_t error;
|
| 1372 | + struct ftl_log_type backup;
|
| 1373 | + if ((*entry).pagescurrent == 0)
|
| 1374 | + {
|
| 1375 | + ftl_release_pool_block((*entry).scatteredvblock);
|
| 1376 | + (*entry).scatteredvblock = 0xFFFF;
|
| 1377 | + return 0;
|
| 1378 | + }
|
| 1379 | + backup = *entry;
|
| 1380 | + memcpy(ftl_offsets_backup, (*entry).pageoffsets, 0x400);
|
| 1381 | + for (i = 0; i < 4; i++)
|
| 1382 | + {
|
| 1383 | + uint32_t block = ftl_allocate_pool_block();
|
| 1384 | + if (block == 0xFFFFFFFF) return 1;
|
| 1385 | + (*entry).pagesused = 0;
|
| 1386 | + (*entry).pagescurrent = 0;
|
| 1387 | + (*entry).issequential = 1;
|
| 1388 | + (*entry).scatteredvblock = block;
|
| 1389 | + error = 0;
|
| 1390 | + for (j = 0; j < ppb; j++)
|
| 1391 | + if ((*entry).pageoffsets[j] != 0xFFFF)
|
| 1392 | + {
|
| 1393 | + uint32_t lpn = (*entry).logicalvblock * ppb + j;
|
| 1394 | + uint32_t newpage = block * ppb + (*entry).pagesused;
|
| 1395 | + uint32_t oldpage = backup.scatteredvblock * ppb
|
| 1396 | + + (*entry).pageoffsets[j];
|
| 1397 | + if (ftl_copy_page(oldpage, newpage, lpn,
|
| 1398 | + (*entry).issequential) != 0)
|
| 1399 | + {
|
| 1400 | + error = 1;
|
| 1401 | + break;
|
| 1402 | + }
|
| 1403 | + (*entry).pageoffsets[j] = (*entry).pagesused++;
|
| 1404 | + (*entry).pagescurrent++;
|
| 1405 | + ftl_check_still_sequential(entry, j);
|
| 1406 | + }
|
| 1407 | + if (backup.pagescurrent != (*entry).pagescurrent) error = 1;
|
| 1408 | + if (error == 0)
|
| 1409 | + {
|
| 1410 | + ftl_release_pool_block(backup.scatteredvblock);
|
| 1411 | + break;
|
| 1412 | + }
|
| 1413 | + *entry = backup;
|
| 1414 | + memcpy((*entry).pageoffsets, ftl_offsets_backup, 0x400);
|
| 1415 | + }
|
| 1416 | + return error;
|
| 1417 | +}
|
| 1418 | +#endif
|
| 1419 | +
|
| 1420 | +
|
| 1421 | +#ifndef FTL_READONLY
|
| 1422 | +/* Commits an ftl_log entry to proper blocks, no matter what's in there. */
|
| 1423 | +uint32_t ftl_commit_scattered(struct ftl_log_type* entry)
|
| 1424 | +{
|
| 1425 | + uint32_t i;
|
| 1426 | + uint32_t error;
|
| 1427 | + uint32_t block;
|
| 1428 | + for (i = 0; i < 4; i++)
|
| 1429 | + {
|
| 1430 | + block = ftl_allocate_pool_block();
|
| 1431 | + if (block == 0xFFFFFFFF) return 1;
|
| 1432 | + error = ftl_copy_block((*entry).logicalvblock, block);
|
| 1433 | + if (error == 0) break;
|
| 1434 | + ftl_release_pool_block(block);
|
| 1435 | + }
|
| 1436 | + if (error != 0) return 1;
|
| 1437 | + ftl_release_pool_block((*entry).scatteredvblock);
|
| 1438 | + (*entry).scatteredvblock = 0xFFFF;
|
| 1439 | + ftl_release_pool_block(ftl_map[(*entry).logicalvblock]);
|
| 1440 | + ftl_map[(*entry).logicalvblock] = block;
|
| 1441 | + return 0;
|
| 1442 | +}
|
| 1443 | +#endif
|
| 1444 | +
|
| 1445 | +
|
| 1446 | +#ifndef FTL_READONLY
|
| 1447 | +/* Fills the rest of a scattered page block that was actually written
|
| 1448 | + sequentially until now, in order to be able to save a block erase by
|
| 1449 | + committing it without needing to copy it again.
|
| 1450 | + If this fails for whichever reason, it will be committed the usual way. */
|
| 1451 | +uint32_t ftl_commit_sequential(struct ftl_log_type* entry)
|
| 1452 | +{
|
| 1453 | + uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
|
| 1454 | +
|
| 1455 | + if ((*entry).issequential != 1
|
| 1456 | + || (*entry).pagescurrent != (*entry).pagesused)
|
| 1457 | + return 1;
|
| 1458 | +
|
| 1459 | + for (; (*entry).pagesused < ppb; (*entry).pagesused++)
|
| 1460 | + {
|
| 1461 | + uint32_t lpn = (*entry).logicalvblock * ppb + (*entry).pagesused;
|
| 1462 | + uint32_t newpage = (*entry).scatteredvblock * ppb
|
| 1463 | + + (*entry).pagesused;
|
| 1464 | + uint32_t oldpage = ftl_map[(*entry).logicalvblock] * ppb
|
| 1465 | + + (*entry).pagesused;
|
| 1466 | + if ((*entry).pageoffsets[(*entry).pagesused] != 0xFFFF
|
| 1467 | + || ftl_copy_page(oldpage, newpage, lpn, 1) != 0)
|
| 1468 | + return ftl_commit_scattered(entry);
|
| 1469 | + }
|
| 1470 | + ftl_release_pool_block(ftl_map[(*entry).logicalvblock]);
|
| 1471 | + ftl_map[(*entry).logicalvblock] = (*entry).scatteredvblock;
|
| 1472 | + (*entry).scatteredvblock = 0xFFFF;
|
| 1473 | + return 0;
|
| 1474 | +}
|
| 1475 | +#endif
|
| 1476 | +
|
| 1477 | +
|
| 1478 | +#ifndef FTL_READONLY
|
| 1479 | +/* If a log entry is supplied, its scattered page block will be removed in
|
| 1480 | + whatever way seems most appropriate. Else, the oldest scattered page block
|
| 1481 | + will be freed by committing it. */
|
| 1482 | +uint32_t ftl_remove_scattered_block(struct ftl_log_type* entry)
|
| 1483 | +{
|
| 1484 | + uint32_t i;
|
| 1485 | + uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
|
| 1486 | + uint32_t age = 0xFFFFFFFF, used = 0;
|
| 1487 | + if (entry == (struct ftl_log_type*)0)
|
| 1488 | + {
|
| 1489 | + for (i = 0; i < 0x11; i++)
|
| 1490 | + {
|
| 1491 | + if (ftl_log[i].scatteredvblock == 0xFFFF) continue;
|
| 1492 | + if (ftl_log[i].pagesused == 0 || ftl_log[i].pagescurrent == 0)
|
| 1493 | + return 1;
|
| 1494 | + if (ftl_log[i].usn < age
|
| 1495 | + || (ftl_log[i].usn == age && ftl_log[i].pagescurrent > used))
|
| 1496 | + {
|
| 1497 | + age = ftl_log[i].usn;
|
| 1498 | + used = ftl_log[i].pagescurrent;
|
| 1499 | + entry = &ftl_log[i];
|
| 1500 | + }
|
| 1501 | + }
|
| 1502 | + if (entry == (struct ftl_log_type*)0) return 1;
|
| 1503 | + }
|
| 1504 | + else if ((*entry).pagescurrent < ppb / 2)
|
| 1505 | + {
|
| 1506 | + ftl_cxt.swapcounter++;
|
| 1507 | + return ftl_compact_scattered(entry);
|
| 1508 | + }
|
| 1509 | + ftl_cxt.swapcounter++;
|
| 1510 | + if ((*entry).issequential == 1) return ftl_commit_sequential(entry);
|
| 1511 | + else return ftl_commit_scattered(entry);
|
| 1512 | +}
|
| 1513 | +#endif
|
| 1514 | +
|
| 1515 | +
|
| 1516 | +#ifndef FTL_READONLY
|
| 1517 | +/* Initialize a log entry to the values for an empty scattered page block */
|
| 1518 | +void ftl_init_log_entry(struct ftl_log_type* entry)
|
| 1519 | +{
|
| 1520 | + (*entry).issequential = 1;
|
| 1521 | + (*entry).pagescurrent = 0;
|
| 1522 | + (*entry).pagesused = 0;
|
| 1523 | + memset((*entry).pageoffsets, 0xFF, 0x400);
|
| 1524 | +}
|
| 1525 | +#endif
|
| 1526 | +
|
| 1527 | +
|
| 1528 | +#ifndef FTL_READONLY
|
| 1529 | +/* Allocates a log entry for the specified vBlock,
|
| 1530 | + first making space, if neccessary. */
|
| 1531 | +struct ftl_log_type* ftl_allocate_log_entry(uint32_t block)
|
| 1532 | +{
|
| 1533 | + uint32_t i;
|
| 1534 | + struct ftl_log_type* entry = ftl_get_log_entry(block);
|
| 1535 | + if (entry != (struct ftl_log_type*)0) return entry;
|
| 1536 | +
|
| 1537 | + for (i = 0; i < 0x11; i++)
|
| 1538 | + {
|
| 1539 | + if (ftl_log[i].scatteredvblock == 0xFFFF) continue;
|
| 1540 | + if (ftl_log[i].pagesused == 0)
|
| 1541 | + {
|
| 1542 | + entry = &ftl_log[i];
|
| 1543 | + break;
|
| 1544 | + }
|
| 1545 | + }
|
| 1546 | +
|
| 1547 | + if (entry == (struct ftl_log_type*)0)
|
| 1548 | + {
|
| 1549 | + if (ftl_cxt.freecount <= 3)
|
| 1550 | + if (ftl_remove_scattered_block((struct ftl_log_type*)0) != 0)
|
| 1551 | + return (struct ftl_log_type*)0;
|
| 1552 | + entry = ftl_log;
|
| 1553 | + while ((*entry).scatteredvblock != 0xFFFF) entry = &entry[1];
|
| 1554 | + (*entry).scatteredvblock = ftl_allocate_pool_block();
|
| 1555 | + if ((*entry).scatteredvblock == 0xFFFF)
|
| 1556 | + {
|
| 1557 | + (*entry).scatteredvblock = 0xFFFF;
|
| 1558 | + return (struct ftl_log_type*)0;
|
| 1559 | + }
|
| 1560 | + }
|
| 1561 | +
|
| 1562 | + ftl_init_log_entry(entry);
|
| 1563 | + (*entry).logicalvblock = block;
|
| 1564 | + (*entry).usn = ftl_cxt.nextblockusn - 1;
|
| 1565 | +
|
| 1566 | + return entry;
|
| 1567 | +}
|
| 1568 | +#endif
|
| 1569 | +
|
| 1570 | +
|
| 1571 | +#ifndef FTL_READONLY
|
| 1572 | +/* Commits the FTL block map, erase counters, and context to flash */
|
| 1573 | +uint32_t ftl_commit_cxt(void)
|
| 1574 | +{
|
| 1575 | + uint32_t i;
|
| 1576 | + uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
|
| 1577 | + uint32_t mappages = ((*ftl_nand_type).userblocks + 0x3ff) >> 10;
|
| 1578 | + uint32_t ctrpages = ((*ftl_nand_type).userblocks + 23 + 0x3ff) >> 10;
|
| 1579 | + uint32_t endpage = ftl_cxt.ftlctrlpage + mappages + ctrpages + 1;
|
| 1580 | + if (endpage % ppb > ppb - 1)
|
| 1581 | + ftl_cxt.ftlctrlpage |= ppb - 1;
|
| 1582 | + for (i = 0; i < ctrpages; i++)
|
| 1583 | + {
|
| 1584 | + if (ftl_next_ctrl_pool_page() != 0) return 1;
|
| 1585 | + if (ftl_save_erasectr_page(i) != 0) return 1;
|
| 1586 | + }
|
| 1587 | + for (i = 0; i < mappages; i++)
|
| 1588 | + {
|
| 1589 | + if (ftl_next_ctrl_pool_page() != 0) return 1;
|
| 1590 | + memset(&ftl_sparebuffer, 0xFF, 0x40);
|
| 1591 | + ftl_sparebuffer.meta.usn = ftl_cxt.usn;
|
| 1592 | + ftl_sparebuffer.meta.idx = i;
|
| 1593 | + ftl_sparebuffer.meta.type = 0x44;
|
| 1594 | + if (ftl_vfl_write(ftl_cxt.ftlctrlpage, &ftl_map[i << 10],
|
| 1595 | + &ftl_sparebuffer) != 0)
|
| 1596 | + return 1;
|
| 1597 | + ftl_cxt.ftl_map_pages[i] = ftl_cxt.ftlctrlpage;
|
| 1598 | + }
|
| 1599 | + if (ftl_next_ctrl_pool_page() != 0) return 1;
|
| 1600 | + ftl_cxt.clean_flag = 1;
|
| 1601 | + memset(&ftl_sparebuffer, 0xFF, 0x40);
|
| 1602 | + ftl_sparebuffer.meta.usn = ftl_cxt.usn;
|
| 1603 | + ftl_sparebuffer.meta.type = 0x43;
|
| 1604 | + if (ftl_vfl_write(ftl_cxt.ftlctrlpage, &ftl_cxt, &ftl_sparebuffer) != 0)
|
| 1605 | + return 1;
|
| 1606 | + return 0;
|
| 1607 | +}
|
| 1608 | +#endif
|
| 1609 | +
|
| 1610 | +
|
| 1611 | +#ifndef FTL_READONLY
|
| 1612 | +/* Swaps the most and least worn block on the flash,
|
| 1613 | + to better distribute wear. It will refuse to do anything
|
| 1614 | + if the wear spread is lower than 5 erases. */
|
| 1615 | +uint32_t ftl_swap_blocks(void)
|
| 1616 | +{
|
| 1617 | + uint32_t i;
|
| 1618 | + uint32_t min = 0xFFFFFFFF, max = 0, maxidx = 0x14;
|
| 1619 | + uint32_t minidx = 0, minvb = 0, maxvb = 0;
|
| 1620 | + for (i = 0; i < ftl_cxt.freecount; i++)
|
| 1621 | + {
|
| 1622 | + uint32_t idx = ftl_cxt.nextfreeidx + i;
|
| 1623 | + if (idx >= 0x14) idx -= 0x14;
|
| 1624 | + if (ftl_erasectr[ftl_cxt.blockpool[idx]] > max)
|
| 1625 | + {
|
| 1626 | + maxidx = idx;
|
| 1627 | + maxvb = ftl_cxt.blockpool[idx];
|
| 1628 | + max = ftl_erasectr[maxidx];
|
| 1629 | + }
|
| 1630 | + }
|
| 1631 | + if (maxidx == 0x14) return 0;
|
| 1632 | + for (i = 0; i < (*ftl_nand_type).userblocks; i++)
|
| 1633 | + {
|
| 1634 | + if (ftl_erasectr[ftl_map[i]] > max) max = ftl_erasectr[ftl_map[i]];
|
| 1635 | + if (ftl_get_log_entry(i) != (struct ftl_log_type*)0) continue;
|
| 1636 | + if (ftl_erasectr[ftl_map[i]] < min)
|
| 1637 | + {
|
| 1638 | + minidx = i;
|
| 1639 | + minvb = ftl_map[i];
|
| 1640 | + min = ftl_erasectr[minidx];
|
| 1641 | + }
|
| 1642 | + }
|
| 1643 | + if (max - min < 5) return 0;
|
| 1644 | + if (minvb == maxvb) return 0;
|
| 1645 | + if (ftl_erase_block(maxvb) != 0) return 1;
|
| 1646 | + if (ftl_copy_block(minidx, maxvb) != 0) return 1;
|
| 1647 | + ftl_cxt.blockpool[maxidx] = minvb;
|
| 1648 | + ftl_map[minidx] = maxvb;
|
| 1649 | + return 0;
|
| 1650 | +}
|
| 1651 | +#endif
|
| 1652 | +
|
| 1653 | +
|
| 1654 | +#ifndef FTL_READONLY
|
| 1655 | +/* Exposed function: Write highlevel sectors */
|
| 1656 | +uint32_t storage_write(uint32_t sector, uint32_t count, const void* buffer)
|
| 1657 | +{
|
| 1658 | + uint32_t i, j;
|
| 1659 | + uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
|
| 1660 | +
|
| 1661 | + if (sector + count > (*ftl_nand_type).userblocks * ppb)
|
| 1662 | + return 1;
|
| 1663 | +
|
| 1664 | + if (count == 0) return 0;
|
| 1665 | +
|
| 1666 | + if (ftl_cxt.clean_flag == 1)
|
| 1667 | + {
|
| 1668 | + for (i = 0; i < 3; i++)
|
| 1669 | + {
|
| 1670 | + if (ftl_next_ctrl_pool_page() != 0) return 1;
|
| 1671 | + memset(ftl_buffer, 0xFF, 0x800);
|
| 1672 | + memset(&ftl_sparebuffer, 0xFF, 0x40);
|
| 1673 | + ftl_sparebuffer.meta.usn = ftl_cxt.usn;
|
| 1674 | + ftl_sparebuffer.meta.type = 0x47;
|
| 1675 | + if (ftl_vfl_write(ftl_cxt.ftlctrlpage, ftl_buffer,
|
| 1676 | + &ftl_sparebuffer) == 0)
|
| 1677 | + break;
|
| 1678 | + }
|
| 1679 | + if (i == 3) return 1;
|
| 1680 | + ftl_cxt.clean_flag = 0;
|
| 1681 | + }
|
| 1682 | +
|
| 1683 | + for (i = 0; i < count; )
|
| 1684 | + {
|
| 1685 | + uint32_t block = (sector + i) / ppb;
|
| 1686 | + uint32_t page = (sector + i) % ppb;
|
| 1687 | +
|
| 1688 | + struct ftl_log_type* logentry = ftl_allocate_log_entry(block);
|
| 1689 | + if (logentry == (struct ftl_log_type*)0) return 1;
|
| 1690 | + if (page == 0 && count - i >= ppb)
|
| 1691 | + {
|
| 1692 | + uint32_t vblock = (*logentry).scatteredvblock;
|
| 1693 | + (*logentry).scatteredvblock = 0xFFFF;
|
| 1694 | + if ((*logentry).pagesused != 0)
|
| 1695 | + {
|
| 1696 | + ftl_release_pool_block(vblock);
|
| 1697 | + vblock = ftl_allocate_pool_block();
|
| 1698 | + if (vblock == 0xFFFFFFFF) return 1;
|
| 1699 | + }
|
| 1700 | + ftl_cxt.nextblockusn++;
|
| 1701 | + for (j = 0; j < ppb; j++)
|
| 1702 | + {
|
| 1703 | + memset(&ftl_sparebuffer, 0xFF, 0x40);
|
| 1704 | + ftl_sparebuffer.user.lpn = sector + i + j;
|
| 1705 | + ftl_sparebuffer.user.usn = ftl_cxt.nextblockusn;
|
| 1706 | + ftl_sparebuffer.user.type = 0x40;
|
| 1707 | + if (j == ppb - 1) ftl_sparebuffer.user.type = 0x41;
|
| 1708 | + while (ftl_vfl_write(vblock * ppb + j,
|
| 1709 | + &((uint8_t*)buffer)[(i + j) << 11],
|
| 1710 | + &ftl_sparebuffer) != 0);
|
| 1711 | + }
|
| 1712 | + ftl_release_pool_block(ftl_map[block]);
|
| 1713 | + ftl_map[block] = vblock;
|
| 1714 | + i += ppb;
|
| 1715 | + }
|
| 1716 | + else
|
| 1717 | + {
|
| 1718 | + if ((*logentry).pagesused == ppb)
|
| 1719 | + {
|
| 1720 | + ftl_remove_scattered_block(logentry);
|
| 1721 | + logentry = ftl_allocate_log_entry(block);
|
| 1722 | + if (logentry == (struct ftl_log_type*)0) return 1;
|
| 1723 | + }
|
| 1724 | + memset(&ftl_sparebuffer, 0xFF, 0x40);
|
| 1725 | + ftl_sparebuffer.user.lpn = sector + i;
|
| 1726 | + ftl_sparebuffer.user.usn = ++ftl_cxt.nextblockusn;
|
| 1727 | + ftl_sparebuffer.user.type = 0x40;
|
| 1728 | + uint32_t abspage = (*logentry).scatteredvblock * ppb
|
| 1729 | + + (*logentry).pagesused++;
|
| 1730 | + if (ftl_vfl_write(abspage, &((uint8_t*)buffer)[i << 11],
|
| 1731 | + &ftl_sparebuffer) == 0)
|
| 1732 | + {
|
| 1733 | + if ((*logentry).pageoffsets[page] == 0xFFFF)
|
| 1734 | + (*logentry).pagescurrent++;
|
| 1735 | + (*logentry).pageoffsets[page] = (*logentry).pagesused - 1;
|
| 1736 | + ftl_check_still_sequential(logentry, page);
|
| 1737 | + i++;
|
| 1738 | + }
|
| 1739 | + }
|
| 1740 | + }
|
| 1741 | + if (ftl_cxt.swapcounter >= 300)
|
| 1742 | + {
|
| 1743 | + ftl_cxt.swapcounter -= 20;
|
| 1744 | + for (i = 0; i < 4; i++) if (ftl_swap_blocks() == 0) break;
|
| 1745 | + }
|
| 1746 | + if (ftl_cxt.erasedirty == 1)
|
| 1747 | + {
|
| 1748 | + ftl_cxt.erasedirty = 0;
|
| 1749 | + for (i = 0; i < 8; i++)
|
| 1750 | + if (ftl_erasectr_dirt[i] >= 100)
|
| 1751 | + {
|
| 1752 | + ftl_next_ctrl_pool_page();
|
| 1753 | + ftl_save_erasectr_page(i);
|
| 1754 | + }
|
| 1755 | + }
|
| 1756 | + return 0;
|
| 1757 | +}
|
| 1758 | +#endif
|
| 1759 | +
|
| 1760 | +
|
| 1761 | +#ifndef FTL_READONLY
|
| 1762 | +// Exposed function: Performes a sync / unmount, i.e. commits all scattered page blocks,
|
| 1763 | +// distributes wear, and commits the FTL context.
|
| 1764 | +uint32_t storage_sync()
|
| 1765 | +{
|
| 1766 | + uint32_t i;
|
| 1767 | + uint32_t rc = 0;
|
| 1768 | + uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
|
| 1769 | + if (ftl_cxt.clean_flag == 1) return 0;
|
| 1770 | +
|
| 1771 | + if (ftl_cxt.swapcounter >= 20)
|
| 1772 | + for (i = 0; i < 4; i++)
|
| 1773 | + if (ftl_swap_blocks() == 0)
|
| 1774 | + {
|
| 1775 | + ftl_cxt.swapcounter -= 20;
|
| 1776 | + break;
|
| 1777 | + }
|
| 1778 | + for (i = 0; i < 0x11; i++)
|
| 1779 | + {
|
| 1780 | + if (ftl_log[i].scatteredvblock == 0xFFFF) continue;
|
| 1781 | + ftl_cxt.nextblockusn++;
|
| 1782 | + if (ftl_log[i].issequential == 1)
|
| 1783 | + rc |= ftl_commit_sequential(&ftl_log[i]);
|
| 1784 | + else rc |= ftl_commit_scattered(&ftl_log[i]);
|
| 1785 | + }
|
| 1786 | + if (rc == 0)
|
| 1787 | + for (i = 0; i < 5; i++)
|
| 1788 | + if (ftl_commit_cxt() == 0) return 0;
|
| 1789 | + else ftl_cxt.ftlctrlpage |= ppb - 1;
|
| 1790 | + return 1;
|
| 1791 | +}
|
| 1792 | +#endif
|
| 1793 | +
|
| 1794 | +
|
| 1795 | +uint32_t storage_get_sector_count()
|
| 1796 | +{
|
| 1797 | + return (*ftl_nand_type).pagesperblock * ftl_banks * (*ftl_nand_type).userblocks;
|
| 1798 | +}
|
| 1799 | +
|
| 1800 | +
|
| 1801 | +/* Initializes and mounts the FTL.
|
| 1802 | + As long as nothing was written, you won't need to unmount it.
|
| 1803 | + Before shutting down after writing something, call storage_sync(),
|
| 1804 | + which will just do nothing if everything was already clean. */
|
| 1805 | +uint32_t storage_init(void)
|
| 1806 | +{
|
| 1807 | + uint32_t i;
|
| 1808 | + uint32_t result = 0;
|
| 1809 | + uint32_t foundsignature, founddevinfo, blockwiped, repaired, skip;
|
| 1810 | +
|
| 1811 | + if (ftl_initialized) return 0;
|
| 1812 | +
|
| 1813 | + if (nand_init() != 0) return 1;
|
| 1814 | + ftl_banks = 0;
|
| 1815 | + for (i = 0; i < 4; i++)
|
| 1816 | + if (nand_get_device_type(i) != 0) ftl_banks = i + 1;
|
| 1817 | + ftl_nand_type = nand_get_device_type(0);
|
| 1818 | + foundsignature = 0;
|
| 1819 | + blockwiped = 1;
|
| 1820 | + for (i = 0; i < (*ftl_nand_type).pagesperblock; i++)
|
| 1821 | + {
|
| 1822 | + result = nand_read_page(0, i, ftl_buffer, (uint32_t*)0, 1, 1);
|
| 1823 | + if ((result & 0x11F) == 0)
|
| 1824 | + {
|
| 1825 | + blockwiped = 0;
|
| 1826 | + if (((uint32_t*)ftl_buffer)[0] != 0x41303034) continue;
|
| 1827 | + foundsignature = 1;
|
| 1828 | + break;
|
| 1829 | + }
|
| 1830 | + else if ((result & 2) != 2) blockwiped = 0;
|
| 1831 | + }
|
| 1832 | + founddevinfo = ftl_has_devinfo();
|
| 1833 | +
|
| 1834 | + repaired = 0;
|
| 1835 | + skip = 0;
|
| 1836 | +
|
| 1837 | + if (founddevinfo == 0) return 1;
|
| 1838 | +
|
| 1839 | + if (foundsignature != 0 && (result & 0x11F) != 0) return 1;
|
| 1840 | +
|
| 1841 | + if (ftl_vfl_open() == 0)
|
| 1842 | + if (ftl_open() == 0)
|
| 1843 | + {
|
| 1844 | + ftl_initialized = 1;
|
| 1845 | + return 0;
|
| 1846 | + }
|
| 1847 | +
|
| 1848 | + return 1;
|
| 1849 | +}
|
Index: embios/branches/4g_compat/target/ipodnano2g/lcd.h |
— | — | @@ -0,0 +1,43 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __LCD_H__
|
| 26 | +#define __LCD_H__
|
| 27 | +
|
| 28 | +
|
| 29 | +#include "global.h"
|
| 30 | +
|
| 31 | +
|
| 32 | +#define LCD_WIDTH 176
|
| 33 | +#define LCD_HEIGHT 132
|
| 34 | +#define LCD_FORMAT rgb565
|
| 35 | +#define LCD_BYTESPERPIXEL 2
|
| 36 | +#define LCD_FRAMEBUFSIZE (LCD_WIDTH * LCD_HEIGHT * LCD_BYTESPERPIXEL)
|
| 37 | +
|
| 38 | +
|
| 39 | +void displaylcd(unsigned int startx, unsigned int endx,
|
| 40 | + unsigned int starty, unsigned int endy, void* data, int color);
|
| 41 | +void displaylcd_sync();
|
| 42 | +
|
| 43 | +
|
| 44 | +#endif
|
Index: embios/branches/4g_compat/target/ipodnano2g/aes.c |
— | — | @@ -0,0 +1,91 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2009 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of the Linux4Nano toolkit.
|
| 8 | +//
|
| 9 | +// TheSeven's iBugger is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// TheSeven's iBugger is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with the Linux4Nano toolkit. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#include <toolkit.h>
|
| 26 | +#include <aes.h>
|
| 27 | +
|
| 28 | +
|
| 29 | +void aes_encrypt(uint32_t keytype, void* data, uint32_t size)
|
| 30 | +{
|
| 31 | + uint32_t ptr, i;
|
| 32 | + uint32_t go = 1;
|
| 33 | + PWRCONEXT &= ~0x400;
|
| 34 | + AESTYPE = keytype;
|
| 35 | + AESUNKREG0 = 1;
|
| 36 | + AESUNKREG0 = 0;
|
| 37 | + AESCONTROL = 1;
|
| 38 | + AESKEYLEN = 9;
|
| 39 | + AESOUTSIZE = size;
|
| 40 | + AESAUXSIZE = 0x10;
|
| 41 | + AESINSIZE = 0x10;
|
| 42 | + AESSIZE3 = 0x10;
|
| 43 | + for (ptr = 0; ptr < (size >> 2); ptr += 4)
|
| 44 | + {
|
| 45 | + AESOUTADDR = (uint32_t)data + (ptr << 2);
|
| 46 | + AESINADDR = (uint32_t)data + (ptr << 2);
|
| 47 | + AESAUXADDR = (uint32_t)data + (ptr << 2);
|
| 48 | + if (ptr != 0)
|
| 49 | + for (i = 0; i < 4; i++)
|
| 50 | + ((uint32_t*)data)[ptr + i] ^= ((uint32_t*)data)[ptr + i - 4];
|
| 51 | + clean_dcache();
|
| 52 | + AESSTATUS = 6;
|
| 53 | + AESGO = go;
|
| 54 | + go = 3;
|
| 55 | + while ((AESSTATUS & 6) == 0);
|
| 56 | + invalidate_dcache();
|
| 57 | + }
|
| 58 | + AESCONTROL = 0;
|
| 59 | + PWRCONEXT |= 0x400;
|
| 60 | +}
|
| 61 | +
|
| 62 | +void aes_decrypt(uint32_t keytype, void* data, uint32_t size)
|
| 63 | +{
|
| 64 | + uint32_t ptr, i;
|
| 65 | + uint32_t go = 1;
|
| 66 | + PWRCONEXT &= ~0x400;
|
| 67 | + AESTYPE = keytype;
|
| 68 | + AESUNKREG0 = 1;
|
| 69 | + AESUNKREG0 = 0;
|
| 70 | + AESCONTROL = 1;
|
| 71 | + AESKEYLEN = 8;
|
| 72 | + AESOUTSIZE = size;
|
| 73 | + AESAUXSIZE = 0x10;
|
| 74 | + AESINSIZE = 0x10;
|
| 75 | + AESSIZE3 = 0x10;
|
| 76 | + for (ptr = (size >> 2) - 4; ; ptr -= 4)
|
| 77 | + {
|
| 78 | + AESOUTADDR = (uint32_t)data + (ptr << 2);
|
| 79 | + AESINADDR = (uint32_t)data + (ptr << 2);
|
| 80 | + AESAUXADDR = (uint32_t)data + (ptr << 2);
|
| 81 | + clean_dcache();
|
| 82 | + AESSTATUS = 6;
|
| 83 | + AESGO = go;
|
| 84 | + go = 3;
|
| 85 | + while ((AESSTATUS & 6) == 0);
|
| 86 | + invalidate_dcache();
|
| 87 | + if (!ptr) break;
|
| 88 | + for (i = 0; i < 4; i++) ((uint32_t*)data)[ptr + i] ^= ((uint32_t*)data)[ptr + i - 4];
|
| 89 | + }
|
| 90 | + AESCONTROL = 0;
|
| 91 | + PWRCONEXT |= 0x400;
|
| 92 | +}
|
Index: embios/branches/4g_compat/target/ipodnano2g/storage.h |
— | — | @@ -0,0 +1,36 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __FTL_H__
|
| 26 | +#define __FTL_H__
|
| 27 | +
|
| 28 | +#include "global.h"
|
| 29 | +
|
| 30 | +uint32_t storage_init();
|
| 31 | +uint32_t storage_read(uint32_t sector, uint32_t count, void* buffer);
|
| 32 | +uint32_t storage_write(uint32_t sector, uint32_t count, const void* buffer);
|
| 33 | +uint32_t storage_sync();
|
| 34 | +uint32_t storage_get_sector_count();
|
| 35 | +
|
| 36 | +
|
| 37 | +#endif
|
Index: embios/branches/4g_compat/target/ipodnano2g/config.h |
— | — | @@ -0,0 +1,28 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2009 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of the Linux4Nano toolkit.
|
| 8 | +//
|
| 9 | +// TheSeven's iBugger is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// TheSeven's iBugger is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with the Linux4Nano toolkit. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +//#define NAND_DEBUG
|
| 26 | +//#define NAND_TRACE
|
| 27 | +//#define VFL_TRACE
|
| 28 | +//#define FTL_TRACE
|
| 29 | +
|
Index: embios/branches/4g_compat/target/ipodnano2g/aes.h |
— | — | @@ -0,0 +1,34 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2009 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of the Linux4Nano toolkit.
|
| 8 | +//
|
| 9 | +// TheSeven's iBugger is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// TheSeven's iBugger is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with the Linux4Nano toolkit. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __AES_H__
|
| 26 | +#define __AES_H__
|
| 27 | +
|
| 28 | +#include <toolkit.h>
|
| 29 | +
|
| 30 | +
|
| 31 | +void aes_encrypt(uint32_t keytype, void* data, uint32_t size);
|
| 32 | +void aes_decrypt(uint32_t keytype, void* data, uint32_t size);
|
| 33 | +
|
| 34 | +
|
| 35 | +#endif
|
Index: embios/branches/4g_compat/target/ipodnano2g/nand.c |
— | — | @@ -0,0 +1,419 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#include "global.h"
|
| 26 | +#include "util.h"
|
| 27 | +#include "timer.h"
|
| 28 | +#include "nand.h"
|
| 29 | +#include "i2c.h"
|
| 30 | +
|
| 31 | +#define NAND_CMD_READ 0x00
|
| 32 | +#define NAND_CMD_PROGCNFRM 0x10
|
| 33 | +#define NAND_CMD_READ2 0x30
|
| 34 | +#define NAND_CMD_BLOCKERASE 0x60
|
| 35 | +#define NAND_CMD_GET_STATUS 0x70
|
| 36 | +#define NAND_CMD_PROGRAM 0x80
|
| 37 | +#define NAND_CMD_ERASECNFRM 0xD0
|
| 38 | +#define NAND_CMD_RESET 0xFF
|
| 39 | +
|
| 40 | +#define NAND_STATUS_READY 0x40
|
| 41 | +
|
| 42 | +#define NAND_DEVICEINFOTABLE_ENTRIES 33
|
| 43 | +
|
| 44 | +static const struct nand_device_info_type nand_deviceinfotable[] =
|
| 45 | +{
|
| 46 | + {0x1580F1EC, 1024, 968, 0x40, 6, 2, 1, 2, 1},
|
| 47 | + {0x1580DAEC, 2048, 1936, 0x40, 6, 2, 1, 2, 1},
|
| 48 | + {0x15C1DAEC, 2048, 1936, 0x40, 6, 2, 1, 2, 1},
|
| 49 | + {0x1510DCEC, 4096, 3872, 0x40, 6, 2, 1, 2, 1},
|
| 50 | + {0x95C1DCEC, 4096, 3872, 0x40, 6, 2, 1, 2, 1},
|
| 51 | + {0x2514DCEC, 2048, 1936, 0x80, 7, 2, 1, 2, 1},
|
| 52 | + {0x2514D3EC, 4096, 3872, 0x80, 7, 2, 1, 2, 1},
|
| 53 | + {0x2555D3EC, 4096, 3872, 0x80, 7, 2, 1, 2, 1},
|
| 54 | + {0x2555D5EC, 8192, 7744, 0x80, 7, 2, 1, 2, 1},
|
| 55 | + {0x2585D3AD, 4096, 3872, 0x80, 7, 3, 2, 3, 2},
|
| 56 | + {0x9580DCAD, 4096, 3872, 0x40, 6, 3, 2, 3, 2},
|
| 57 | + {0xA514D3AD, 4096, 3872, 0x80, 7, 3, 2, 3, 2},
|
| 58 | + {0xA550D3AD, 4096, 3872, 0x80, 7, 3, 2, 3, 2},
|
| 59 | + {0xA560D5AD, 4096, 3872, 0x80, 7, 3, 2, 3, 2},
|
| 60 | + {0xA555D5AD, 8192, 7744, 0x80, 7, 3, 2, 3, 2},
|
| 61 | + {0xA585D598, 8320, 7744, 0x80, 7, 3, 1, 2, 1},
|
| 62 | + {0xA584D398, 4160, 3872, 0x80, 7, 3, 1, 2, 1},
|
| 63 | + {0x95D1D32C, 8192, 7744, 0x40, 6, 2, 1, 2, 1},
|
| 64 | + {0x1580DC2C, 4096, 3872, 0x40, 6, 2, 1, 2, 1},
|
| 65 | + {0x15C1D32C, 8192, 7744, 0x40, 6, 2, 1, 2, 1},
|
| 66 | + {0x9590DC2C, 4096, 3872, 0x40, 6, 2, 1, 2, 1},
|
| 67 | + {0xA594D32C, 4096, 3872, 0x80, 7, 2, 1, 2, 1},
|
| 68 | + {0x2584DC2C, 2048, 1936, 0x80, 7, 2, 1, 2, 1},
|
| 69 | + {0xA5D5D52C, 8192, 7744, 0x80, 7, 3, 2, 2, 1},
|
| 70 | + {0x95D1D389, 8192, 7744, 0x40, 6, 2, 1, 2, 1},
|
| 71 | + {0x1580DC89, 4096, 3872, 0x40, 6, 2, 1, 2, 1},
|
| 72 | + {0x15C1D389, 8192, 7744, 0x40, 6, 2, 1, 2, 1},
|
| 73 | + {0x9590DC89, 4096, 3872, 0x40, 6, 2, 1, 2, 1},
|
| 74 | + {0xA594D389, 4096, 3872, 0x80, 7, 2, 1, 2, 1},
|
| 75 | + {0x2584DC89, 2048, 1936, 0x80, 7, 2, 1, 2, 1},
|
| 76 | + {0xA5D5D589, 8192, 7744, 0x80, 7, 2, 1, 2, 1},
|
| 77 | + {0xA514D320, 4096, 3872, 0x80, 7, 2, 1, 2, 1},
|
| 78 | + {0xA555D520, 8192, 3872, 0x80, 7, 2, 1, 2, 1}
|
| 79 | +};
|
| 80 | +
|
| 81 | +uint8_t nand_tunk1[4];
|
| 82 | +uint8_t nand_twp[4];
|
| 83 | +uint8_t nand_tunk2[4];
|
| 84 | +uint8_t nand_tunk3[4];
|
| 85 | +uint32_t nand_type[4];
|
| 86 | +
|
| 87 | +static uint8_t nand_ctrl[0x200] __attribute__((aligned(16)));
|
| 88 | +static uint8_t nand_spare[0x40] __attribute__((aligned(16)));
|
| 89 | +static uint8_t nand_ecc[0x30] __attribute__((aligned(16)));
|
| 90 | +
|
| 91 | +
|
| 92 | +uint32_t nand_wait_rbbdone(void)
|
| 93 | +{
|
| 94 | + uint32_t timeout = USEC_TIMER;
|
| 95 | + while ((FMCSTAT & FMCSTAT_RBBDONE) == 0) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
|
| 96 | + FMCSTAT = FMCSTAT_RBBDONE;
|
| 97 | + return 0;
|
| 98 | +}
|
| 99 | +
|
| 100 | +uint32_t nand_wait_cmddone(void)
|
| 101 | +{
|
| 102 | + uint32_t timeout = USEC_TIMER;
|
| 103 | + while ((FMCSTAT & FMCSTAT_CMDDONE) == 0) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
|
| 104 | + FMCSTAT = FMCSTAT_CMDDONE;
|
| 105 | + return 0;
|
| 106 | +}
|
| 107 | +
|
| 108 | +uint32_t nand_wait_addrdone(void)
|
| 109 | +{
|
| 110 | + uint32_t timeout = USEC_TIMER;
|
| 111 | + while ((FMCSTAT & FMCSTAT_ADDRDONE) == 0) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
|
| 112 | + FMCSTAT = FMCSTAT_ADDRDONE;
|
| 113 | + return 0;
|
| 114 | +}
|
| 115 | +
|
| 116 | +uint32_t nand_wait_chip_ready(uint32_t bank)
|
| 117 | +{
|
| 118 | + uint32_t timeout = USEC_TIMER;
|
| 119 | + while ((FMCSTAT & (FMCSTAT_BANK0READY << bank)) == 0) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
|
| 120 | + FMCSTAT = (FMCSTAT_BANK0READY << bank);
|
| 121 | + return 0;
|
| 122 | +}
|
| 123 | +
|
| 124 | +void nand_set_fmctrl0(uint32_t bank, uint32_t flags)
|
| 125 | +{
|
| 126 | + FMCTRL0 = (nand_tunk1[bank] << 16) | (nand_twp[bank] << 12)
|
| 127 | + | (1 << 11) | 1 | (1 << (bank + 1)) | flags;
|
| 128 | +}
|
| 129 | +
|
| 130 | +uint32_t nand_send_cmd(uint32_t cmd)
|
| 131 | +{
|
| 132 | + FMCMD = cmd;
|
| 133 | + return nand_wait_rbbdone();
|
| 134 | +}
|
| 135 | +
|
| 136 | +uint32_t nand_send_address(uint32_t page, uint32_t offset)
|
| 137 | +{
|
| 138 | + FMANUM = 4;
|
| 139 | + FMADDR0 = (page << 16) | offset;
|
| 140 | + FMADDR1 = (page >> 16) & 0xFF;
|
| 141 | + FMCTRL1 = FMCTRL1_DOTRANSADDR;
|
| 142 | + return nand_wait_cmddone();
|
| 143 | +}
|
| 144 | +
|
| 145 | +uint32_t nand_reset(uint32_t bank)
|
| 146 | +{
|
| 147 | + nand_set_fmctrl0(bank, 0);
|
| 148 | + if (nand_send_cmd(NAND_CMD_RESET)) return 1;
|
| 149 | + if (nand_wait_chip_ready(bank)) return 1;
|
| 150 | + FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
|
| 151 | + sleep(1000);
|
| 152 | + return 0;
|
| 153 | +}
|
| 154 | +
|
| 155 | +uint32_t nand_wait_status_ready(uint32_t bank)
|
| 156 | +{
|
| 157 | + uint32_t timeout = USEC_TIMER;
|
| 158 | + nand_set_fmctrl0(bank, 0);
|
| 159 | + if ((FMCSTAT & (FMCSTAT_BANK0READY << bank)))
|
| 160 | + FMCSTAT = (FMCSTAT_BANK0READY << bank);
|
| 161 | + FMCTRL1 = FMCTRL1_CLEARRFIFO;
|
| 162 | + if (nand_send_cmd(NAND_CMD_GET_STATUS)) return 1;
|
| 163 | + while (1)
|
| 164 | + {
|
| 165 | + if (TIMEOUT_EXPIRED(timeout, 200)) return 1;
|
| 166 | + FMDNUM = 0;
|
| 167 | + FMCTRL1 = FMCTRL1_DOREADDATA;
|
| 168 | + if (nand_wait_addrdone()) return 1;
|
| 169 | + if ((FMFIFO & NAND_STATUS_READY)) break;
|
| 170 | + FMCTRL1 = FMCTRL1_CLEARRFIFO;
|
| 171 | + }
|
| 172 | + FMCTRL1 = FMCTRL1_CLEARRFIFO;
|
| 173 | + return nand_send_cmd(NAND_CMD_READ);
|
| 174 | +}
|
| 175 | +
|
| 176 | +uint32_t nand_transfer_data(uint32_t bank, uint32_t direction, void* buffer, uint32_t size)
|
| 177 | +{
|
| 178 | + uint32_t timeout = USEC_TIMER;
|
| 179 | + nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
|
| 180 | + FMDNUM = size - 1;
|
| 181 | + FMCTRL1 = FMCTRL1_DOREADDATA << direction;
|
| 182 | + DMACON3 = (2 << DMACON_DEVICE_SHIFT)
|
| 183 | + | (direction << DMACON_DIRECTION_SHIFT)
|
| 184 | + | (2 << DMACON_DATA_SIZE_SHIFT)
|
| 185 | + | (3 << DMACON_BURST_LEN_SHIFT);
|
| 186 | + while ((DMAALLST & DMAALLST_CHAN3_MASK))
|
| 187 | + DMACOM3 = DMACOM_CLEARBOTHDONE;
|
| 188 | + DMABASE3 = (uint32_t)buffer;
|
| 189 | + DMATCNT3 = (size >> 4) - 1;
|
| 190 | + clean_dcache();
|
| 191 | + DMACOM3 = 4;
|
| 192 | + while ((DMAALLST & DMAALLST_DMABUSY3)) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
|
| 193 | + if (!direction) invalidate_dcache();
|
| 194 | + if (nand_wait_addrdone()) return 1;
|
| 195 | + if (!direction) FMCTRL1 = FMCTRL1_CLEARRFIFO | FMCTRL1_CLEARWFIFO;
|
| 196 | + else FMCTRL1 = FMCTRL1_CLEARRFIFO;
|
| 197 | + return 0;
|
| 198 | +}
|
| 199 | +
|
| 200 | +uint32_t ecc_decode(uint32_t size, void* databuffer, void* sparebuffer)
|
| 201 | +{
|
| 202 | + uint32_t timeout = USEC_TIMER;
|
| 203 | + ECC_INT_CLR = 1;
|
| 204 | + SRCPND = INTMSK_ECC;
|
| 205 | + ECC_UNK1 = size;
|
| 206 | + ECC_DATA_PTR = (uint32_t)databuffer;
|
| 207 | + ECC_SPARE_PTR = (uint32_t)sparebuffer;
|
| 208 | + clean_dcache();
|
| 209 | + ECC_CTRL = ECCCTRL_STARTDECODING;
|
| 210 | + while (!(SRCPND & INTMSK_ECC)) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
|
| 211 | + invalidate_dcache();
|
| 212 | + ECC_INT_CLR = 1;
|
| 213 | + SRCPND = INTMSK_ECC;
|
| 214 | + return ECC_RESULT;
|
| 215 | +}
|
| 216 | +
|
| 217 | +uint32_t ecc_encode(uint32_t size, void* databuffer, void* sparebuffer)
|
| 218 | +{
|
| 219 | + uint32_t timeout = USEC_TIMER;
|
| 220 | + ECC_INT_CLR = 1;
|
| 221 | + SRCPND = INTMSK_ECC;
|
| 222 | + ECC_UNK1 = size;
|
| 223 | + ECC_DATA_PTR = (uint32_t)databuffer;
|
| 224 | + ECC_SPARE_PTR = (uint32_t)sparebuffer;
|
| 225 | + clean_dcache();
|
| 226 | + ECC_CTRL = ECCCTRL_STARTENCODING;
|
| 227 | + while (!(SRCPND & INTMSK_ECC)) if (TIMEOUT_EXPIRED(timeout, 2000)) return 1;
|
| 228 | + invalidate_dcache();
|
| 229 | + ECC_INT_CLR = 1;
|
| 230 | + SRCPND = INTMSK_ECC;
|
| 231 | + return 0;
|
| 232 | +}
|
| 233 | +
|
| 234 | +uint32_t nand_check_empty(uint8_t* buffer)
|
| 235 | +{
|
| 236 | + uint32_t i, count;
|
| 237 | + count = 0;
|
| 238 | + for (i = 0; i < 0x40; i++) if (buffer[i] != 0xFF) count++;
|
| 239 | + if (count < 2) return 1;
|
| 240 | + return 0;
|
| 241 | +}
|
| 242 | +
|
| 243 | +uint32_t nand_get_chip_type(uint32_t bank)
|
| 244 | +{
|
| 245 | + uint32_t result;
|
| 246 | + if (nand_reset(bank)) return 0xFFFFFFFF;
|
| 247 | + if (nand_send_cmd(0x90)) return 0xFFFFFFFF;
|
| 248 | + FMANUM = 0;
|
| 249 | + FMADDR0 = 0;
|
| 250 | + FMCTRL1 = FMCTRL1_DOTRANSADDR;
|
| 251 | + if (nand_wait_cmddone()) return 0xFFFFFFFF;
|
| 252 | + FMDNUM = 4;
|
| 253 | + FMCTRL1 = FMCTRL1_DOREADDATA;
|
| 254 | + if (nand_wait_addrdone()) return 0xFFFFFFFF;
|
| 255 | + result = FMFIFO;
|
| 256 | + FMCTRL1 = FMCTRL1_CLEARRFIFO;
|
| 257 | + return result;
|
| 258 | +}
|
| 259 | +
|
| 260 | +uint32_t nand_read_page(uint32_t bank, uint32_t page, void* data,
|
| 261 | + void* sparebuffer, uint32_t doecc, uint32_t checkempty)
|
| 262 | +{
|
| 263 | + uint32_t rc, eccresult;
|
| 264 | + uint8_t* spare = nand_spare;
|
| 265 | + if (sparebuffer) spare = sparebuffer;
|
| 266 | + nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
|
| 267 | + if (nand_send_cmd(NAND_CMD_READ)) return 1;
|
| 268 | + if (nand_send_address(page, data ? 0 : 0x800)) return 1;
|
| 269 | + if (nand_send_cmd(NAND_CMD_READ2)) return 1;
|
| 270 | + if (nand_wait_status_ready(bank)) return 1;
|
| 271 | + if (data) if (nand_transfer_data(bank, 0, data, 0x800)) return 1;
|
| 272 | + rc = 0;
|
| 273 | + if (!doecc)
|
| 274 | + {
|
| 275 | + if (sparebuffer)
|
| 276 | + {
|
| 277 | + if (nand_transfer_data(bank, 0, spare, 0x40)) return 1;
|
| 278 | + if (checkempty)
|
| 279 | + rc = nand_check_empty((uint8_t*)spare) << 1;
|
| 280 | + }
|
| 281 | + return rc;
|
| 282 | + }
|
| 283 | + if (nand_transfer_data(bank, 0, spare, 0x40)) return 1;
|
| 284 | + if (data)
|
| 285 | + {
|
| 286 | + memcpy(nand_ecc, &((uint8_t*)spare)[0xC], 0x28);
|
| 287 | + rc |= (ecc_decode(3, data, nand_ecc) & 0xF) << 4;
|
| 288 | + }
|
| 289 | + memset(nand_ctrl, 0xFF, 0x200);
|
| 290 | + memcpy(nand_ctrl, spare, 0xC);
|
| 291 | + memcpy(nand_ecc, &((uint8_t*)spare)[0x34], 0xC);
|
| 292 | + eccresult = ecc_decode(0, nand_ctrl, nand_ecc);
|
| 293 | + rc |= (eccresult & 0xF) << 8;
|
| 294 | + if (spare)
|
| 295 | + {
|
| 296 | + if (eccresult & 1) memset(spare, 0xFF, 0xC);
|
| 297 | + else memcpy(spare, nand_ctrl, 0xC);
|
| 298 | + }
|
| 299 | + if (checkempty) rc |= nand_check_empty(spare) << 1;
|
| 300 | + return rc;
|
| 301 | +}
|
| 302 | +
|
| 303 | +uint32_t nand_write_page(uint32_t bank, uint32_t page, void* data,
|
| 304 | + void* sparebuffer, uint32_t doecc)
|
| 305 | +{
|
| 306 | + uint8_t* spare = nand_spare;
|
| 307 | + if (sparebuffer) spare = sparebuffer;
|
| 308 | + else memset(spare, 0xFF, 0x40);
|
| 309 | + if (doecc)
|
| 310 | + {
|
| 311 | + if (ecc_encode(3, data, nand_ecc)) return 1;
|
| 312 | + memcpy(&spare[0xC], nand_ecc, 0x28);
|
| 313 | + memset(nand_ctrl, 0xFF, 0x200);
|
| 314 | + memcpy(nand_ctrl, spare, 0xC);
|
| 315 | + if (ecc_encode(0, nand_ctrl, nand_ecc)) return 1;
|
| 316 | + memcpy(&spare[0x34], nand_ecc, 0xC);
|
| 317 | + }
|
| 318 | + nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA);
|
| 319 | + if (nand_send_cmd(NAND_CMD_PROGRAM)) return 1;
|
| 320 | + if (nand_send_address(page, data ? 0 : 0x800)) return 1;
|
| 321 | + if (data) if (nand_transfer_data(bank, 1, data, 0x800)) return 1;
|
| 322 | + if (sparebuffer || doecc)
|
| 323 | + if (nand_transfer_data(bank, 1, spare, 0x40)) return 1;
|
| 324 | + if (nand_send_cmd(NAND_CMD_PROGCNFRM)) return 1;
|
| 325 | + return nand_wait_status_ready(bank);
|
| 326 | +}
|
| 327 | +
|
| 328 | +uint32_t nand_block_erase(uint32_t bank, uint32_t page)
|
| 329 | +{
|
| 330 | + nand_set_fmctrl0(bank, 0);
|
| 331 | + if (nand_send_cmd(NAND_CMD_BLOCKERASE)) return 1;
|
| 332 | + FMANUM = 2;
|
| 333 | + FMADDR0 = page;
|
| 334 | + FMCTRL1 = FMCTRL1_DOTRANSADDR;
|
| 335 | + if (nand_wait_cmddone()) return 1;
|
| 336 | + if (nand_send_cmd(NAND_CMD_ERASECNFRM)) return 1;
|
| 337 | + return nand_wait_status_ready(bank);
|
| 338 | +}
|
| 339 | +
|
| 340 | +uint32_t nand_block_erase_fast(uint32_t page)
|
| 341 | +{
|
| 342 | + uint32_t i, rc = 0;
|
| 343 | + for (i = 0; i < 4; i++)
|
| 344 | + {
|
| 345 | + if (nand_type[i] == 0xFFFFFFFF) continue;
|
| 346 | + nand_set_fmctrl0(i, 0);
|
| 347 | + if (nand_send_cmd(NAND_CMD_BLOCKERASE))
|
| 348 | + {
|
| 349 | + rc |= 1 << i;
|
| 350 | + continue;
|
| 351 | + }
|
| 352 | + FMANUM = 2;
|
| 353 | + FMADDR0 = page;
|
| 354 | + FMCTRL1 = FMCTRL1_DOTRANSADDR;
|
| 355 | + if (nand_wait_cmddone())
|
| 356 | + {
|
| 357 | + rc |= 1 << i;
|
| 358 | + continue;
|
| 359 | + }
|
| 360 | + if (nand_send_cmd(NAND_CMD_ERASECNFRM)) rc |= 1 << i;
|
| 361 | + }
|
| 362 | + for (i = 0; i < 4; i++)
|
| 363 | + {
|
| 364 | + if (nand_type[i] == 0xFFFFFFFF) continue;
|
| 365 | + if (rc & (1 << i)) continue;
|
| 366 | + if (nand_wait_status_ready(i)) rc |= 1 << i;
|
| 367 | + }
|
| 368 | + return rc;
|
| 369 | +}
|
| 370 | +
|
| 371 | +const struct nand_device_info_type* nand_get_device_type(uint32_t bank)
|
| 372 | +{
|
| 373 | + if (nand_type[bank] == 0xFFFFFFFF)
|
| 374 | + return (struct nand_device_info_type*)0;
|
| 375 | + return &nand_deviceinfotable[nand_type[bank]];
|
| 376 | +}
|
| 377 | +
|
| 378 | +uint32_t nand_init()
|
| 379 | +{
|
| 380 | + uint32_t type;
|
| 381 | + uint32_t i, j;
|
| 382 | + PWRCONEXT &= ~0x40;
|
| 383 | + PWRCON &= ~0x100010;
|
| 384 | + i2csendbyte(0xE6, 0x35, 0x15);
|
| 385 | + i2csendbyte(0xE6, 0x36, 0x01);
|
| 386 | + PCON2 = 0x33333333;
|
| 387 | + PDAT2 = 0;
|
| 388 | + PCON3 = 0x11113333;
|
| 389 | + PDAT3 = 0;
|
| 390 | + PCON4 = 0x33333333;
|
| 391 | + PDAT4 = 0;
|
| 392 | + PCON5 = (PCON5 & ~0xF) | 3;
|
| 393 | + PUNK5 = 1;
|
| 394 | + sleep(10000);
|
| 395 | + for (i = 0; i < 4; i++)
|
| 396 | + {
|
| 397 | + nand_tunk1[i] = 7;
|
| 398 | + nand_twp[i] = 7;
|
| 399 | + nand_tunk2[i] = 7;
|
| 400 | + nand_tunk3[i] = 7;
|
| 401 | + type = nand_get_chip_type(i);
|
| 402 | + nand_type[i] = 0xFFFFFFFF;
|
| 403 | + if (type == 0xFFFFFFFF) continue;
|
| 404 | + for (j = 0; ; j++)
|
| 405 | + {
|
| 406 | + if (j == NAND_DEVICEINFOTABLE_ENTRIES) break;
|
| 407 | + else if (nand_deviceinfotable[j].id == type)
|
| 408 | + {
|
| 409 | + nand_type[i] = j;
|
| 410 | + break;
|
| 411 | + }
|
| 412 | + }
|
| 413 | + nand_tunk1[i] = nand_deviceinfotable[nand_type[i]].tunk1;
|
| 414 | + nand_twp[i] = nand_deviceinfotable[nand_type[i]].twp;
|
| 415 | + nand_tunk2[i] = nand_deviceinfotable[nand_type[i]].tunk2;
|
| 416 | + nand_tunk3[i] = nand_deviceinfotable[nand_type[i]].tunk3;
|
| 417 | + }
|
| 418 | + if (nand_type[0] == 0xFFFFFFFF) return 1;
|
| 419 | + return 0;
|
| 420 | +}
|
Index: embios/branches/4g_compat/target/ipodnano2g/i2c.h |
— | — | @@ -0,0 +1,37 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __I2C_H__
|
| 26 | +#define __I2C_H__
|
| 27 | +
|
| 28 | +
|
| 29 | +#include "global.h"
|
| 30 | +
|
| 31 | +
|
| 32 | +extern void i2csend(uint32_t device, uint32_t address, void* data, uint32_t length);
|
| 33 | +extern void i2crecv(uint32_t device, uint32_t address, void* data, uint32_t length);
|
| 34 | +extern void i2csendbyte(uint32_t device, uint32_t address, uint32_t data);
|
| 35 | +extern uint32_t i2crecvbyte(uint32_t device, uint32_t address);
|
| 36 | +
|
| 37 | +
|
| 38 | +#endif
|
Index: embios/branches/4g_compat/target/ipodnano2g/hash.c |
— | — | @@ -0,0 +1,42 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2009 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of the Linux4Nano toolkit.
|
| 8 | +//
|
| 9 | +// TheSeven's iBugger is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// TheSeven's iBugger is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with the Linux4Nano toolkit. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#include <toolkit.h>
|
| 26 | +#include <hash.h>
|
| 27 | +
|
| 28 | +
|
| 29 | +void hash(void* data, uint32_t size, void* result)
|
| 30 | +{
|
| 31 | + uint32_t ptr, i;
|
| 32 | + uint32_t ctrl = 2;
|
| 33 | + PWRCONEXT &= ~4;
|
| 34 | + for (ptr = 0; ptr < size; ptr += 0x10)
|
| 35 | + {
|
| 36 | + for (i = 0; i < 0x10; i++) HASHDATAIN[i] = ((uint32_t*)data)[ptr + i];
|
| 37 | + HASHCTRL = ctrl;
|
| 38 | + ctrl = 0xA;
|
| 39 | + while (HASHCTRL & 1);
|
| 40 | + }
|
| 41 | + for (i = 0; i < 5; i ++) ((uint32_t*)result)[i] = HASHRESULT[i];
|
| 42 | + PWRCONEXT |= 4;
|
| 43 | +}
|
Index: embios/branches/4g_compat/target/ipodnano2g/timer.h |
— | — | @@ -0,0 +1,42 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __TIMER_H__
|
| 26 | +#define __TIMER_H__
|
| 27 | +
|
| 28 | +#include "global.h"
|
| 29 | +
|
| 30 | +
|
| 31 | +#define TIME_AFTER(a,b) ((long)(b) - (long)(a) < 0)
|
| 32 | +#define TIME_BEFORE(a,b) TIME_AFTER(b,a)
|
| 33 | +#define TIMEOUT_EXPIRED(a,b) TIME_AFTER(USEC_TIMER,a + b)
|
| 34 | +
|
| 35 | +
|
| 36 | +static inline void sleep(long duration) /* in usec steps */
|
| 37 | +{
|
| 38 | + long timestamp = USEC_TIMER;
|
| 39 | + while (!TIMEOUT_EXPIRED(timestamp, duration));
|
| 40 | +}
|
| 41 | +
|
| 42 | +
|
| 43 | +#endif
|
Index: embios/branches/4g_compat/target/ipodnano2g/nand.h |
— | — | @@ -0,0 +1,62 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __NAND_H__
|
| 26 | +#define __NAND_H__
|
| 27 | +
|
| 28 | +#include "global.h"
|
| 29 | +
|
| 30 | +
|
| 31 | +struct nand_device_info_type
|
| 32 | +{
|
| 33 | + uint32_t id;
|
| 34 | + uint16_t blocks;
|
| 35 | + uint16_t userblocks;
|
| 36 | + uint16_t pagesperblock;
|
| 37 | + uint8_t blocksizeexponent;
|
| 38 | + uint8_t tunk1;
|
| 39 | + uint8_t twp;
|
| 40 | + uint8_t tunk2;
|
| 41 | + uint8_t tunk3;
|
| 42 | +} __attribute__((packed));
|
| 43 | +
|
| 44 | +uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer,
|
| 45 | + void* sparebuffer, uint32_t doecc,
|
| 46 | + uint32_t checkempty);
|
| 47 | +uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer,
|
| 48 | + void* sparebuffer, uint32_t doecc);
|
| 49 | +uint32_t nand_block_erase(uint32_t bank, uint32_t page);
|
| 50 | +
|
| 51 | +uint32_t nand_read_page_fast(uint32_t page, void* databuffer,
|
| 52 | + void* sparebuffer, uint32_t doecc,
|
| 53 | + uint32_t checkempty);
|
| 54 | +uint32_t nand_write_page_fast(uint32_t page, void* databuffer,
|
| 55 | + void* sparebuffer, uint32_t doecc);
|
| 56 | +uint32_t nand_block_erase_fast(uint32_t page);
|
| 57 | +
|
| 58 | +const struct nand_device_info_type* nand_get_device_type(uint32_t bank);
|
| 59 | +uint32_t nand_reset(uint32_t bank);
|
| 60 | +uint32_t nand_init();
|
| 61 | +
|
| 62 | +
|
| 63 | +#endif
|
Index: embios/branches/4g_compat/target/ipodnano2g/s5l8701.h |
— | — | @@ -0,0 +1,245 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __S5L8701_H__
|
| 26 | +#define __S5L8701_H__
|
| 27 | +
|
| 28 | +#include "global.h"
|
| 29 | +
|
| 30 | +
|
| 31 | +/////CLKCON/////
|
| 32 | +#define CLKCON (*((volatile uint32_t*)(0x3C500000)))
|
| 33 | +#define PLL0PMS (*((volatile uint32_t*)(0x3C500004)))
|
| 34 | +#define PLL1PMS (*((volatile uint32_t*)(0x3C500008)))
|
| 35 | +#define PLL2PMS (*((volatile uint32_t*)(0x3C50000C)))
|
| 36 | +#define PLL0LCNT (*((volatile uint32_t*)(0x3C500014)))
|
| 37 | +#define PLL1LCNT (*((volatile uint32_t*)(0x3C500018)))
|
| 38 | +#define PLL2LCNT (*((volatile uint32_t*)(0x3C50001C)))
|
| 39 | +#define PLLLOCK (*((volatile uint32_t*)(0x3C500020)))
|
| 40 | +#define PLLCON (*((volatile uint32_t*)(0x3C500024)))
|
| 41 | +#define PWRCON (*((volatile uint32_t*)(0x3C500028)))
|
| 42 | +#define PWRMODE (*((volatile uint32_t*)(0x3C50002C)))
|
| 43 | +#define SWRCON (*((volatile uint32_t*)(0x3C500030)))
|
| 44 | +#define RSTSR (*((volatile uint32_t*)(0x3C500034)))
|
| 45 | +#define DSPCLKMD (*((volatile uint32_t*)(0x3C500038)))
|
| 46 | +#define CLKCON2 (*((volatile uint32_t*)(0x3C50003C)))
|
| 47 | +#define PWRCONEXT (*((volatile uint32_t*)(0x3C500040)))
|
| 48 | +
|
| 49 | +
|
| 50 | +/////ICU/////
|
| 51 | +#define SRCPND (*((volatile uint32_t*)(0x39C00000)))
|
| 52 | +#define INTMOD (*((volatile uint32_t*)(0x39C00004)))
|
| 53 | +#define INTMSK (*((volatile uint32_t*)(0x39C00008)))
|
| 54 | +#define INTPRIO (*((volatile uint32_t*)(0x39C0000C)))
|
| 55 | +#define INTPND (*((volatile uint32_t*)(0x39C00010)))
|
| 56 | +#define INTOFFSET (*((volatile uint32_t*)(0x39C00014)))
|
| 57 | +#define EINTPOL (*((volatile uint32_t*)(0x39C00018)))
|
| 58 | +#define EINTPEND (*((volatile uint32_t*)(0x39C0001C)))
|
| 59 | +#define EINTMSK (*((volatile uint32_t*)(0x39C00020)))
|
| 60 | +
|
| 61 | +
|
| 62 | +/////GPIO/////
|
| 63 | +#define PCON0 (*((volatile uint32_t*)(0x3CF00000)))
|
| 64 | +#define PDAT0 (*((volatile uint32_t*)(0x3CF00004)))
|
| 65 | +#define PCON1 (*((volatile uint32_t*)(0x3CF00010)))
|
| 66 | +#define PDAT1 (*((volatile uint32_t*)(0x3CF00014)))
|
| 67 | +#define PCON2 (*((volatile uint32_t*)(0x3CF00020)))
|
| 68 | +#define PDAT2 (*((volatile uint32_t*)(0x3CF00024)))
|
| 69 | +#define PCON3 (*((volatile uint32_t*)(0x3CF00030)))
|
| 70 | +#define PDAT3 (*((volatile uint32_t*)(0x3CF00034)))
|
| 71 | +#define PCON4 (*((volatile uint32_t*)(0x3CF00040)))
|
| 72 | +#define PDAT4 (*((volatile uint32_t*)(0x3CF00044)))
|
| 73 | +#define PCON5 (*((volatile uint32_t*)(0x3CF00050)))
|
| 74 | +#define PDAT5 (*((volatile uint32_t*)(0x3CF00054)))
|
| 75 | +#define PUNK5 (*((volatile uint32_t*)(0x3CF0005C)))
|
| 76 | +#define PCON6 (*((volatile uint32_t*)(0x3CF00060)))
|
| 77 | +#define PDAT6 (*((volatile uint32_t*)(0x3CF00064)))
|
| 78 | +#define PCON7 (*((volatile uint32_t*)(0x3CF00070)))
|
| 79 | +#define PDAT7 (*((volatile uint32_t*)(0x3CF00074)))
|
| 80 | +#define PCON10 (*((volatile uint32_t*)(0x3CF000A0)))
|
| 81 | +#define PDAT10 (*((volatile uint32_t*)(0x3CF000A4)))
|
| 82 | +#define PCON15 (*((volatile uint32_t*)(0x3CF000F0)))
|
| 83 | +#define PUNK15 (*((volatile uint32_t*)(0x3CF000FC)))
|
| 84 | +
|
| 85 | +
|
| 86 | +/////IODMA/////
|
| 87 | +#define DMABASE0 (*((volatile uint32_t*)(0x38400000)))
|
| 88 | +#define DMACON0 (*((volatile uint32_t*)(0x38400004)))
|
| 89 | +#define DMATCNT0 (*((volatile uint32_t*)(0x38400008)))
|
| 90 | +#define DMACADDR0 (*((volatile uint32_t*)(0x3840000C)))
|
| 91 | +#define DMACTCNT0 (*((volatile uint32_t*)(0x38400010)))
|
| 92 | +#define DMACOM0 (*((volatile uint32_t*)(0x38400014)))
|
| 93 | +#define DMANOF0 (*((volatile uint32_t*)(0x38400018)))
|
| 94 | +#define DMABASE1 (*((volatile uint32_t*)(0x38400020)))
|
| 95 | +#define DMACON1 (*((volatile uint32_t*)(0x38400024)))
|
| 96 | +#define DMATCNT1 (*((volatile uint32_t*)(0x38400028)))
|
| 97 | +#define DMACADDR1 (*((volatile uint32_t*)(0x3840002C)))
|
| 98 | +#define DMACTCNT1 (*((volatile uint32_t*)(0x38400030)))
|
| 99 | +#define DMACOM1 (*((volatile uint32_t*)(0x38400034)))
|
| 100 | +#define DMABASE2 (*((volatile uint32_t*)(0x38400040)))
|
| 101 | +#define DMACON2 (*((volatile uint32_t*)(0x38400044)))
|
| 102 | +#define DMATCNT2 (*((volatile uint32_t*)(0x38400048)))
|
| 103 | +#define DMACADDR2 (*((volatile uint32_t*)(0x3840004C)))
|
| 104 | +#define DMACTCNT2 (*((volatile uint32_t*)(0x38400050)))
|
| 105 | +#define DMACOM2 (*((volatile uint32_t*)(0x38400054)))
|
| 106 | +#define DMABASE3 (*((volatile uint32_t*)(0x38400060)))
|
| 107 | +#define DMACON3 (*((volatile uint32_t*)(0x38400064)))
|
| 108 | +#define DMATCNT3 (*((volatile uint32_t*)(0x38400068)))
|
| 109 | +#define DMACADDR3 (*((volatile uint32_t*)(0x3840006C)))
|
| 110 | +#define DMACTCNT3 (*((volatile uint32_t*)(0x38400070)))
|
| 111 | +#define DMACOM3 (*((volatile uint32_t*)(0x38400074)))
|
| 112 | +#define DMABASE4 (*((volatile uint32_t*)(0x38400080)))
|
| 113 | +#define DMACON4 (*((volatile uint32_t*)(0x38400084)))
|
| 114 | +#define DMATCNT4 (*((volatile uint32_t*)(0x38400088)))
|
| 115 | +#define DMACADDR4 (*((volatile uint32_t*)(0x3840008C)))
|
| 116 | +#define DMACTCNT4 (*((volatile uint32_t*)(0x38400090)))
|
| 117 | +#define DMACOM4 (*((volatile uint32_t*)(0x38400094)))
|
| 118 | +#define DMABASE5 (*((volatile uint32_t*)(0x384000A0)))
|
| 119 | +#define DMACON5 (*((volatile uint32_t*)(0x384000A4)))
|
| 120 | +#define DMATCNT5 (*((volatile uint32_t*)(0x384000A8)))
|
| 121 | +#define DMACADDR5 (*((volatile uint32_t*)(0x384000AC)))
|
| 122 | +#define DMACTCNT5 (*((volatile uint32_t*)(0x384000B0)))
|
| 123 | +#define DMACOM5 (*((volatile uint32_t*)(0x384000B4)))
|
| 124 | +#define DMABASE6 (*((volatile uint32_t*)(0x384000C0)))
|
| 125 | +#define DMACON6 (*((volatile uint32_t*)(0x384000C4)))
|
| 126 | +#define DMATCNT6 (*((volatile uint32_t*)(0x384000C8)))
|
| 127 | +#define DMACADDR6 (*((volatile uint32_t*)(0x384000CC)))
|
| 128 | +#define DMACTCNT6 (*((volatile uint32_t*)(0x384000D0)))
|
| 129 | +#define DMACOM6 (*((volatile uint32_t*)(0x384000D4)))
|
| 130 | +#define DMABASE7 (*((volatile uint32_t*)(0x384000E0)))
|
| 131 | +#define DMACON7 (*((volatile uint32_t*)(0x384000E4)))
|
| 132 | +#define DMATCNT7 (*((volatile uint32_t*)(0x384000E8)))
|
| 133 | +#define DMACADDR7 (*((volatile uint32_t*)(0x384000EC)))
|
| 134 | +#define DMACTCNT7 (*((volatile uint32_t*)(0x384000F0)))
|
| 135 | +#define DMACOM7 (*((volatile uint32_t*)(0x384000F4)))
|
| 136 | +#define DMAALLST (*((volatile uint32_t*)(0x38400180)))
|
| 137 | +#define DMACON_DEVICE_SHIFT 30
|
| 138 | +#define DMACON_DIRECTION_SHIFT 29
|
| 139 | +#define DMACON_DATA_SIZE_SHIFT 22
|
| 140 | +#define DMACON_BURST_LEN_SHIFT 19
|
| 141 | +#define DMACOM_START 4
|
| 142 | +#define DMACOM_CLEARBOTHDONE 7
|
| 143 | +#define DMAALLST_WCOM0 (1 << 0)
|
| 144 | +#define DMAALLST_HCOM0 (1 << 1)
|
| 145 | +#define DMAALLST_DMABUSY0 (1 << 2)
|
| 146 | +#define DMAALLST_HOLD_SKIP (1 << 3)
|
| 147 | +#define DMAALLST_WCOM1 (1 << 4)
|
| 148 | +#define DMAALLST_HCOM1 (1 << 5)
|
| 149 | +#define DMAALLST_DMABUSY1 (1 << 6)
|
| 150 | +#define DMAALLST_WCOM2 (1 << 8)
|
| 151 | +#define DMAALLST_HCOM2 (1 << 9)
|
| 152 | +#define DMAALLST_DMABUSY2 (1 << 10)
|
| 153 | +#define DMAALLST_WCOM3 (1 << 12)
|
| 154 | +#define DMAALLST_HCOM3 (1 << 13)
|
| 155 | +#define DMAALLST_DMABUSY3 (1 << 14)
|
| 156 | +#define DMAALLST_CHAN0_MASK (0xF << 0)
|
| 157 | +#define DMAALLST_CHAN1_MASK (0xF << 4)
|
| 158 | +#define DMAALLST_CHAN2_MASK (0xF << 8)
|
| 159 | +#define DMAALLST_CHAN3_MASK (0xF << 12)
|
| 160 | +
|
| 161 | +
|
| 162 | +/////FMC/////
|
| 163 | +#define FMCTRL0 (*((volatile uint32_t*)(0x39400000)))
|
| 164 | +#define FMCTRL1 (*((volatile uint32_t*)(0x39400004)))
|
| 165 | +#define FMCMD (*((volatile uint32_t*)(0x39400008)))
|
| 166 | +#define FMADDR0 (*((volatile uint32_t*)(0x3940000C)))
|
| 167 | +#define FMADDR1 (*((volatile uint32_t*)(0x39400010)))
|
| 168 | +#define FMANUM (*((volatile uint32_t*)(0x3940002C)))
|
| 169 | +#define FMDNUM (*((volatile uint32_t*)(0x39400030)))
|
| 170 | +#define FMCSTAT (*((volatile uint32_t*)(0x39400048)))
|
| 171 | +#define FMFIFO (*((volatile uint32_t*)(0x39400080)))
|
| 172 | +#define RS_ECC_CTRL (*((volatile uint32_t*)(0x39400100)))
|
| 173 | +#define FMCTRL0_ENABLEDMA (1 << 10)
|
| 174 | +#define FMCTRL0_UNK1 (1 << 11)
|
| 175 | +#define FMCTRL1_DOTRANSADDR (1 << 0)
|
| 176 | +#define FMCTRL1_DOREADDATA (1 << 1)
|
| 177 | +#define FMCTRL1_DOWRITEDATA (1 << 2)
|
| 178 | +#define FMCTRL1_CLEARWFIFO (1 << 6)
|
| 179 | +#define FMCTRL1_CLEARRFIFO (1 << 7)
|
| 180 | +#define FMCSTAT_RBB (1 << 0)
|
| 181 | +#define FMCSTAT_RBBDONE (1 << 1)
|
| 182 | +#define FMCSTAT_CMDDONE (1 << 2)
|
| 183 | +#define FMCSTAT_ADDRDONE (1 << 3)
|
| 184 | +#define FMCSTAT_BANK0READY (1 << 4)
|
| 185 | +#define FMCSTAT_BANK1READY (1 << 5)
|
| 186 | +#define FMCSTAT_BANK2READY (1 << 6)
|
| 187 | +#define FMCSTAT_BANK3READY (1 << 7)
|
| 188 | +
|
| 189 | +
|
| 190 | +/////ECC/////
|
| 191 | +#define ECC_DATA_PTR (*((volatile uint32_t*)(0x39E00004)))
|
| 192 | +#define ECC_SPARE_PTR (*((volatile uint32_t*)(0x39E00008)))
|
| 193 | +#define ECC_CTRL (*((volatile uint32_t*)(0x39E0000C)))
|
| 194 | +#define ECC_RESULT (*((volatile uint32_t*)(0x39E00010)))
|
| 195 | +#define ECC_UNK1 (*((volatile uint32_t*)(0x39E00014)))
|
| 196 | +#define ECC_INT_CLR (*((volatile uint32_t*)(0x39E00040)))
|
| 197 | +#define INTMSK_ECC 0x80000
|
| 198 | +#define ECCCTRL_STARTDECODING (1 << 0)
|
| 199 | +#define ECCCTRL_STARTENCODING (1 << 1)
|
| 200 | +#define ECCCTRL_STARTDECNOSYND (1 << 2)
|
| 201 | +
|
| 202 | +
|
| 203 | +/////CLICKWHEEL/////
|
| 204 | +#define WHEEL00 (*((volatile uint32_t*)(0x3C200000)))
|
| 205 | +#define WHEEL04 (*((volatile uint32_t*)(0x3C200004)))
|
| 206 | +#define WHEEL08 (*((volatile uint32_t*)(0x3C200008)))
|
| 207 | +#define WHEEL0C (*((volatile uint32_t*)(0x3C20000C)))
|
| 208 | +#define WHEEL10 (*((volatile uint32_t*)(0x3C200010)))
|
| 209 | +#define WHEELINT (*((volatile uint32_t*)(0x3C200014)))
|
| 210 | +#define WHEELRX (*((volatile uint32_t*)(0x3C200018)))
|
| 211 | +#define WHEELTX (*((volatile uint32_t*)(0x3C20001C)))
|
| 212 | +
|
| 213 | +
|
| 214 | +/////AES/////
|
| 215 | +#define AESCONTROL (*((volatile uint32_t*)(0x39800000)))
|
| 216 | +#define AESGO (*((volatile uint32_t*)(0x39800004)))
|
| 217 | +#define AESUNKREG0 (*((volatile uint32_t*)(0x39800008)))
|
| 218 | +#define AESSTATUS (*((volatile uint32_t*)(0x3980000C)))
|
| 219 | +#define AESUNKREG1 (*((volatile uint32_t*)(0x39800010)))
|
| 220 | +#define AESKEYLEN (*((volatile uint32_t*)(0x39800014)))
|
| 221 | +#define AESOUTSIZE (*((volatile uint32_t*)(0x39800018)))
|
| 222 | +#define AESOUTADDR (*((volatile uint32_t*)(0x39800020)))
|
| 223 | +#define AESINSIZE (*((volatile uint32_t*)(0x39800024)))
|
| 224 | +#define AESINADDR (*((volatile uint32_t*)(0x39800028)))
|
| 225 | +#define AESAUXSIZE (*((volatile uint32_t*)(0x3980002C)))
|
| 226 | +#define AESAUXADDR (*((volatile uint32_t*)(0x39800030)))
|
| 227 | +#define AESSIZE3 (*((volatile uint32_t*)(0x39800034)))
|
| 228 | +#define AESKEY ((volatile uint32_t*)(0x3980004C))
|
| 229 | +#define AESTYPE (*((volatile uint32_t*)(0x3980006C)))
|
| 230 | +#define AESIV ((volatile uint32_t*)(0x39800074))
|
| 231 | +#define AESTYPE2 (*((volatile uint32_t*)(0x39800088)))
|
| 232 | +#define AESUNKREG2 (*((volatile uint32_t*)(0x3980008C)))
|
| 233 | +
|
| 234 | +/////HASH/////
|
| 235 | +#define HASHCTRL (*((volatile uint32_t*)(0x3C600000)))
|
| 236 | +#define HASHRESULT ((volatile uint32_t*)(0x3C600020))
|
| 237 | +#define HASHDATAIN ((volatile uint32_t*)(0x3C600040))
|
| 238 | +
|
| 239 | +
|
| 240 | +/////TIMER/////
|
| 241 | +#define FIVE_USEC_TIMER (((uint64_t)(*((volatile uint32_t*)(0x3C700080))) << 32) \
|
| 242 | + | (*((volatile uint32_t*)(0x3C700084)))) /* 64bit 5usec timer */
|
| 243 | +#define USEC_TIMER ((long)(FIVE_USEC_TIMER * 5)) /* usecs */
|
| 244 | +
|
| 245 | +
|
| 246 | +#endif
|
Index: embios/branches/4g_compat/target/ipodnano2g/hash.h |
— | — | @@ -0,0 +1,33 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2009 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of the Linux4Nano toolkit.
|
| 8 | +//
|
| 9 | +// TheSeven's iBugger is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// TheSeven's iBugger is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with the Linux4Nano toolkit. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __HASH_H__
|
| 26 | +#define __HASH_H__
|
| 27 | +
|
| 28 | +#include <toolkit.h>
|
| 29 | +
|
| 30 | +
|
| 31 | +void hash(void* data, uint32_t size, void* result);
|
| 32 | +
|
| 33 | +
|
| 34 | +#endif
|
Index: embios/branches/4g_compat/target/ipodnano2g/crt0.S |
— | — | @@ -0,0 +1,187 @@ |
| 2 | +@
|
| 3 | +@
|
| 4 | +@ Copyright 2010 TheSeven
|
| 5 | +@
|
| 6 | +@
|
| 7 | +@ This file is part of emBIOS.
|
| 8 | +@
|
| 9 | +@ emBIOS is free software: you can redistribute it and/or
|
| 10 | +@ modify it under the terms of the GNU General Public License as
|
| 11 | +@ published by the Free Software Foundation, either version 2 of the
|
| 12 | +@ License, or (at your option) any later version.
|
| 13 | +@
|
| 14 | +@ emBIOS is distributed in the hope that it will be useful,
|
| 15 | +@ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +@ See the GNU General Public License for more details.
|
| 18 | +@
|
| 19 | +@ You should have received a copy of the GNU General Public License
|
| 20 | +@ along with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +@
|
| 22 | +@
|
| 23 | +
|
| 24 | +
|
| 25 | +.section .intvect,"ax",%progbits
|
| 26 | + ldr pc, =reset_handler
|
| 27 | + ldr pc, =undef_instr_handler
|
| 28 | + ldr pc, =syscall_handler
|
| 29 | + ldr pc, =prefetch_abort_handler
|
| 30 | + ldr pc, =data_abort_handler
|
| 31 | + ldr pc, =reserved_handler
|
| 32 | + ldr pc, =irq_handler
|
| 33 | + ldr pc, =fiq_handler
|
| 34 | +.ltorg
|
| 35 | +
|
| 36 | +
|
| 37 | +.section .initcode,"ax",%progbits
|
| 38 | +.global _start
|
| 39 | +_start:
|
| 40 | + ldr r0, =_sramsource
|
| 41 | + ldr r1, =_sramstart
|
| 42 | + ldr r2, =_sramend
|
| 43 | +.copysram:
|
| 44 | + cmp r2, r1
|
| 45 | + ldrhi r3, [r0], #4
|
| 46 | + strhi r3, [r1], #4
|
| 47 | + bhi .copysram
|
| 48 | + ldr r0, =_sdramsource
|
| 49 | + ldr r1, =_sdramstart
|
| 50 | + ldr r2, =_sdramend
|
| 51 | +.copysdram:
|
| 52 | + cmp r2, r1
|
| 53 | + ldrhi r3, [r0], #4
|
| 54 | + strhi r3, [r1], #4
|
| 55 | + bhi .copysdram
|
| 56 | + ldr r0, =_initbssstart
|
| 57 | + ldr r1, =_initbssend
|
| 58 | + mov r2, #0
|
| 59 | +.clearinitbss:
|
| 60 | + cmp r1, r0
|
| 61 | + strhi r2, [r0], #4
|
| 62 | + bhi .clearinitbss
|
| 63 | + ldr r0, =_ibssstart
|
| 64 | + ldr r1, =_ibssend
|
| 65 | +.clearibss:
|
| 66 | + cmp r1, r0
|
| 67 | + strhi r2, [r0], #4
|
| 68 | + bhi .clearibss
|
| 69 | + ldr r0, =_bssstart
|
| 70 | + ldr r1, =_bssend
|
| 71 | +.clearbss:
|
| 72 | + cmp r1, r0
|
| 73 | + strhi r2, [r0], #4
|
| 74 | + bhi .clearbss
|
| 75 | + ldr r1, =0x38200000
|
| 76 | + ldr r0, [r1]
|
| 77 | + orr r0, r0, #1
|
| 78 | + bic r0, r0, #0x10000
|
| 79 | + str r0, [r1]
|
| 80 | + mov r0, #0
|
| 81 | + mcr p15, 0, r0,c7,c5,0
|
| 82 | + msr cpsr_c, #0xd2
|
| 83 | + ldr sp, =_irqstackend
|
| 84 | + msr cpsr_c, #0xd7
|
| 85 | + ldr sp, =_abortstackend
|
| 86 | + msr cpsr_c, #0xdb
|
| 87 | + ldr sp, =_abortstackend
|
| 88 | + msr cpsr_c, #0xd3
|
| 89 | + ldr sp, =_initstackend
|
| 90 | + bl init
|
| 91 | + b main
|
| 92 | +.ltorg
|
| 93 | +
|
| 94 | +
|
| 95 | +.section .icode, "ax", %progbits
|
| 96 | +.align 2
|
| 97 | +.global reset
|
| 98 | +.global hang
|
| 99 | +.type reset, %function
|
| 100 | +.type hang, %function
|
| 101 | +reset:
|
| 102 | + msr cpsr_c, #0xd3
|
| 103 | + mov r0, #0x110000
|
| 104 | + add r0, r0, #0xff
|
| 105 | + add r1, r0, #0xa00
|
| 106 | + mov r2, #0x3c800000
|
| 107 | + str r1, [r2]
|
| 108 | + mov r1, #0xff0
|
| 109 | + str r1, [r2,#4]
|
| 110 | + str r0, [r2]
|
| 111 | +hang:
|
| 112 | + b hang
|
| 113 | +.size reset, .-reset
|
| 114 | +.size hang, .-hang
|
| 115 | +
|
| 116 | +.type reset_handler, %function
|
| 117 | +reset_handler:
|
| 118 | + adr r0, reset_text
|
| 119 | + b panic
|
| 120 | +reset_text:
|
| 121 | + .ascii "Hit reset vector!\0"
|
| 122 | +.size reset_handler, .-reset_handler
|
| 123 | +
|
| 124 | +.type undef_instr_handler, %function
|
| 125 | +undef_instr_handler:
|
| 126 | + adr r0, undef_instr_text
|
| 127 | + sub r0, lr, #4
|
| 128 | + b panicf
|
| 129 | +.size undef_instr_handler, .-undef_instr_handler
|
| 130 | +
|
| 131 | +.type prefetch_abort_handler, %function
|
| 132 | +prefetch_abort_handler:
|
| 133 | + adr r0, prefetch_abort_text
|
| 134 | + sub r0, lr, #4
|
| 135 | + b panicf
|
| 136 | +.size prefetch_abort_handler, .-prefetch_abort_handler
|
| 137 | +
|
| 138 | +.type data_abort_handler, %function
|
| 139 | +data_abort_handler:
|
| 140 | + adr r0, data_abort_text
|
| 141 | + sub r0, lr, #4
|
| 142 | + b panicf
|
| 143 | +.size data_abort_handler, .-data_abort_handler
|
| 144 | +
|
| 145 | +.type reserved_handler, %function
|
| 146 | +reserved_handler:
|
| 147 | + adr r0, reserved_text
|
| 148 | + b panic
|
| 149 | +.size reserved_handler, .-reserved_handler
|
| 150 | +
|
| 151 | +.type fiq_handler, %function
|
| 152 | +fiq_handler:
|
| 153 | + adr r0, fiq_text
|
| 154 | + b panic
|
| 155 | +.size fiq_handler, .-fiq_handler
|
| 156 | +
|
| 157 | +.type irq_handler, %function
|
| 158 | +irq_handler:
|
| 159 | + adr r0, irq_text
|
| 160 | + b panic
|
| 161 | +.size irq_handler, .-irq_handler
|
| 162 | +
|
| 163 | +.type syscall_handler, %function
|
| 164 | +syscall_handler:
|
| 165 | + adr r0, syscall_text
|
| 166 | + b panic
|
| 167 | +.size syscall_handler, .-syscall_handler
|
| 168 | +
|
| 169 | +undef_instr_text:
|
| 170 | + .ascii "Undefined instruction at %08X!\0"
|
| 171 | +
|
| 172 | +prefetch_abort_text:
|
| 173 | + .ascii "Prefetch abort at %08X!\0"
|
| 174 | +
|
| 175 | +data_abort_text:
|
| 176 | + .ascii "Data abort at %08X!\0"
|
| 177 | +
|
| 178 | +reserved_text:
|
| 179 | + .ascii "Hit reserved exception handler!\0"
|
| 180 | +
|
| 181 | +fiq_text:
|
| 182 | + .ascii "Unhandled FIQ!\0"
|
| 183 | +
|
| 184 | +irq_text:
|
| 185 | + .ascii "Unhandled IRQ!\0"
|
| 186 | +
|
| 187 | +syscall_text:
|
| 188 | + .ascii "Unhandled syscall!\0"
|
Index: embios/branches/4g_compat/target/ipodnano2g/target.h |
— | — | @@ -0,0 +1,34 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __TARGET_H__
|
| 26 | +#define __TARGET_H__
|
| 27 | +
|
| 28 | +
|
| 29 | +#include "s5l8701.h"
|
| 30 | +
|
| 31 | +
|
| 32 | +#define ARM_ARCH 4
|
| 33 | +
|
| 34 | +
|
| 35 | +#endif
|
Index: embios/branches/4g_compat/target/ipodnano2g/i2c.S |
— | — | @@ -0,0 +1,135 @@ |
| 2 | +@
|
| 3 | +@
|
| 4 | +@ Copyright 2010 TheSeven
|
| 5 | +@
|
| 6 | +@
|
| 7 | +@ This file is part of emBIOS.
|
| 8 | +@
|
| 9 | +@ emBIOS is free software: you can redistribute it and/or
|
| 10 | +@ modify it under the terms of the GNU General Public License as
|
| 11 | +@ published by the Free Software Foundation, either version 2 of the
|
| 12 | +@ License, or (at your option) any later version.
|
| 13 | +@
|
| 14 | +@ emBIOS is distributed in the hope that it will be useful,
|
| 15 | +@ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +@ See the GNU General Public License for more details.
|
| 18 | +@
|
| 19 | +@ You should have received a copy of the GNU General Public License
|
| 20 | +@ along with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +@
|
| 22 | +@
|
| 23 | +
|
| 24 | +
|
| 25 | +.section .icode.i2csend, "ax", %progbits
|
| 26 | +.align 2
|
| 27 | +.global i2csendbyte
|
| 28 | +.global i2csend
|
| 29 | +.type i2csendbyte, %function
|
| 30 | +.type i2csend, %function
|
| 31 | +i2csendbyte:
|
| 32 | + mov r3, #0
|
| 33 | +@fallthrough
|
| 34 | +
|
| 35 | +i2csend:
|
| 36 | + stmfd sp!, {r4,lr}
|
| 37 | + mov r12, #0x3C000000
|
| 38 | + add r12, r12, #0x00900000
|
| 39 | + mov r4, #0
|
| 40 | + str r4, [r12,#0x08]
|
| 41 | + str r0, [r12,#0x0c]
|
| 42 | + mov r4, #0xf0
|
| 43 | + str r4, [r12,#0x04]
|
| 44 | + mov r4, #0xf3
|
| 45 | + str r4, [r12]
|
| 46 | + bl i2cwait
|
| 47 | + str r1, [r12,#0x0c]
|
| 48 | + str r4, [r12]
|
| 49 | + bl i2cwait
|
| 50 | + movs r3, r3
|
| 51 | + moveq r0, r2
|
| 52 | +i2csend_write:
|
| 53 | + ldrne r0, [r2], #1
|
| 54 | + str r0, [r12,#0x0c]
|
| 55 | + str r4, [r12]
|
| 56 | + bl i2cwait
|
| 57 | + subs r3, r3, #1
|
| 58 | + bhi i2csend_write
|
| 59 | + mov r0, #0xd0
|
| 60 | + str r0, [r12,#0x04]
|
| 61 | + str r4, [r12]
|
| 62 | +i2csend_wait:
|
| 63 | + ldr r0, [r12,#0x04]
|
| 64 | + tst r0, #0x20
|
| 65 | + bne i2csend_wait
|
| 66 | + ldmfd sp!, {r4,pc}
|
| 67 | +.size i2csendbyte, .-i2csendbyte
|
| 68 | +.size i2csend, .-i2csend
|
| 69 | +
|
| 70 | +
|
| 71 | +.section .icode.i2crecv, "ax", %progbits
|
| 72 | +.align 2
|
| 73 | +.global i2crecvbyte
|
| 74 | +.global i2crecv
|
| 75 | +.type i2crecvbyte, %function
|
| 76 | +.type i2crecv, %function
|
| 77 | +i2crecvbyte:
|
| 78 | + mov r2, #0
|
| 79 | + mov r3, #1
|
| 80 | +@fallthrough
|
| 81 | +
|
| 82 | +i2crecv:
|
| 83 | + stmfd sp!, {r0,r4,lr}
|
| 84 | + mov r12, #0x3C000000
|
| 85 | + add r12, r12, #0x00900000
|
| 86 | + mov r4, #0
|
| 87 | + str r4, [r12,#0x08]
|
| 88 | + str r0, [r12,#0x0c]
|
| 89 | + mov r4, #0xf0
|
| 90 | + str r4, [r12,#0x04]
|
| 91 | + mov r4, #0xf3
|
| 92 | + str r4, [r12]
|
| 93 | + bl i2cwait
|
| 94 | + str r1, [r12,#0x0c]
|
| 95 | + str r4, [r12]
|
| 96 | + bl i2cwait
|
| 97 | + ldr r0, [sp]
|
| 98 | + orr r0, r0, #1
|
| 99 | + str r1, [r12,#0x0c]
|
| 100 | + mov r0, #0xb0
|
| 101 | + str r0, [r12,#0x04]
|
| 102 | + str r4, [r12]
|
| 103 | + bl i2cwait
|
| 104 | +i2crecv_read:
|
| 105 | + subs r3, r3, #1
|
| 106 | + moveq r4, #0x73
|
| 107 | + str r4, [r12]
|
| 108 | + bl i2cwait
|
| 109 | + ldr r0, [r12,#0x0c]
|
| 110 | + movs r2, r2
|
| 111 | + strne r0, [r2], #1
|
| 112 | + movs r3, r3
|
| 113 | + bne i2crecv_read
|
| 114 | + mov r1, #0x90
|
| 115 | + str r1, [r12,#0x04]
|
| 116 | + mov r1, #0xf3
|
| 117 | + str r1, [r12]
|
| 118 | +i2crecv_wait:
|
| 119 | + ldr r1, [r12,#0x04]
|
| 120 | + tst r1, #0x20
|
| 121 | + bne i2crecv_wait
|
| 122 | + ldmfd sp!, {r0,r4,pc}
|
| 123 | +.size i2crecvbyte, .-i2crecvbyte
|
| 124 | +.size i2crecv, .-i2crecv
|
| 125 | +
|
| 126 | +
|
| 127 | +.section .icode.i2cwait, "ax", %progbits
|
| 128 | +.align 2
|
| 129 | +.global i2cwait
|
| 130 | +.type i2cwait, %function
|
| 131 | +i2cwait:
|
| 132 | + ldr r0, [r12]
|
| 133 | + tst r0, #0x10
|
| 134 | + beq i2cwait
|
| 135 | + mov pc, lr
|
| 136 | +.size i2cwait, .-i2cwait
|
Index: embios/branches/4g_compat/drawing.h |
— | — | @@ -0,0 +1,39 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __DRAWING_H__
|
| 26 | +#define __DRAWING_H__
|
| 27 | +
|
| 28 | +
|
| 29 | +#include "global.h"
|
| 30 | +
|
| 31 | +
|
| 32 | +#define FONT_WIDTH 6
|
| 33 | +#define FONT_HEIGHT 8
|
| 34 | +
|
| 35 | +
|
| 36 | +void rendertext(void* buffer, int fgcol, int bgcol, char* text, int stride);
|
| 37 | +void renderbmp(void* buffer, void* bitmap, int stride);
|
| 38 | +
|
| 39 | +
|
| 40 | +#endif
|
Index: embios/branches/4g_compat/drawing.S |
— | — | @@ -0,0 +1,230 @@ |
| 2 | +@
|
| 3 | +@
|
| 4 | +@ Copyright 2010 TheSeven
|
| 5 | +@
|
| 6 | +@
|
| 7 | +@ This file is part of emBIOS.
|
| 8 | +@
|
| 9 | +@ emBIOS is free software: you can redistribute it and/or
|
| 10 | +@ modify it under the terms of the GNU General Public License as
|
| 11 | +@ published by the Free Software Foundation, either version 2 of the
|
| 12 | +@ License, or (at your option) any later version.
|
| 13 | +@
|
| 14 | +@ emBIOS is distributed in the hope that it will be useful,
|
| 15 | +@ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +@ See the GNU General Public License for more details.
|
| 18 | +@
|
| 19 | +@ You should have received a copy of the GNU General Public License
|
| 20 | +@ along with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +@
|
| 22 | +@
|
| 23 | +
|
| 24 | +
|
| 25 | +.section .icode.renderbmp, "ax", %progbits
|
| 26 | +.align 2
|
| 27 | +.global renderbmp
|
| 28 | +.type renderbmp, %function
|
| 29 | +renderbmp:
|
| 30 | + ldrh r2, [r1]
|
| 31 | + sub r2, r2, #0x4d00
|
| 32 | + subs r2, r2, #0x42
|
| 33 | + movne pc, lr
|
| 34 | + stmfd sp!, {r4,lr}
|
| 35 | + ldrh r2, [r1,#18]
|
| 36 | + ldrh r12, [r1,#20]
|
| 37 | + orr r2, r2, r12,lsl#16
|
| 38 | + ldrh r4, [r1,#22]
|
| 39 | + ldrh r12, [r1,#24]
|
| 40 | + orr r4, r4, r12,lsl#16
|
| 41 | + ldrh lr, [r1,#10]
|
| 42 | + ldrh r12, [r1,#12]
|
| 43 | + orr lr, lr, r12,lsl#16
|
| 44 | + add r1, r1, lr
|
| 45 | + mov r12, #352
|
| 46 | + mul lr, r12, r4
|
| 47 | + add r0, r0, lr
|
| 48 | +renderbmp_row:
|
| 49 | + mov r12, r2
|
| 50 | + sub r0, r0, r3
|
| 51 | +renderbmp_pixel:
|
| 52 | + ldrb lr, [r1,#1]
|
| 53 | + strb lr, [r0], #1
|
| 54 | + ldrb lr, [r1], #2
|
| 55 | + strb lr, [r0], #1
|
| 56 | + subs r12, r12, #1
|
| 57 | + bne renderbmp_pixel
|
| 58 | + tst r2, #1
|
| 59 | + addne r1, r1, #2
|
| 60 | + sub r0, r0, r2,lsl#1
|
| 61 | + subs r4, r4, #1
|
| 62 | + bne renderbmp_row
|
| 63 | + ldmfd sp!, {r4,pc}
|
| 64 | +.size renderbmp, .-renderbmp
|
| 65 | +
|
| 66 | +
|
| 67 | +.section .icode.renderchar, "ax", %progbits
|
| 68 | +.align 2
|
| 69 | +.global renderchar
|
| 70 | +.type renderchar, %function
|
| 71 | +renderchar:
|
| 72 | + stmfd sp!, {r4-r7,lr}
|
| 73 | + ldr r7, [sp,#0x14]
|
| 74 | + cmn r2, #1
|
| 75 | + beq renderchar_nobg
|
| 76 | + mov r6, r0
|
| 77 | + mov r4, #8
|
| 78 | + mov lr, r2,lsr#16
|
| 79 | + sub lr, lr, #0xff00
|
| 80 | + subs lr, lr, #0xff
|
| 81 | + bne renderchar_opaquerow
|
| 82 | + mov r12, r2,lsl#16
|
| 83 | + mov r12, r12,lsr#16
|
| 84 | +renderchar_blendrow:
|
| 85 | + mov r5, #6
|
| 86 | +renderchar_blendcol:
|
| 87 | + ldrh lr, [r6]
|
| 88 | + tst lr, #1
|
| 89 | + orrne lr, lr, #0x10000
|
| 90 | + mov lr, lr,lsr#1
|
| 91 | + bic lr, lr, #0x1000
|
| 92 | + bic lr, lr, #0x84
|
| 93 | + add lr, lr, r12
|
| 94 | + strh lr, [r6], #2
|
| 95 | + subs r5, r5, #1
|
| 96 | + bne renderchar_blendcol
|
| 97 | + add r6, r6, r7
|
| 98 | + sub r6, r6, #12
|
| 99 | + subs r4, r4, #1
|
| 100 | + bne renderchar_blendrow
|
| 101 | + b renderchar_nobg
|
| 102 | +renderchar_opaquerow:
|
| 103 | + mov r5, #6
|
| 104 | +renderchar_opaquecol:
|
| 105 | + strh r2, [r6], #2
|
| 106 | + subs r5, r5, #1
|
| 107 | + bne renderchar_opaquecol
|
| 108 | + add r6, r6, r7
|
| 109 | + sub r6, r6, #12
|
| 110 | + subs r4, r4, #1
|
| 111 | + bne renderchar_opaquerow
|
| 112 | +renderchar_nobg:
|
| 113 | + adr r5, renderchar_font
|
| 114 | + sub r3, r3, #0x20
|
| 115 | + cmp r3, #0x5f
|
| 116 | + addcc r5, r3,lsl#2
|
| 117 | + addcc r5, r3
|
| 118 | + mov r3, #5
|
| 119 | +renderchar_col:
|
| 120 | + mov r6, r0
|
| 121 | + ldrb r4, [r5], #1
|
| 122 | +renderchar_row:
|
| 123 | + tst r4, #1
|
| 124 | + strneh r1, [r6]
|
| 125 | + add r6, r6, r7
|
| 126 | + movs r4, r4,lsr#1
|
| 127 | + bne renderchar_row
|
| 128 | + add r0, r0, #2
|
| 129 | + subs r3, r3, #1
|
| 130 | + bne renderchar_col
|
| 131 | + add r0, r0, #2
|
| 132 | + ldmfd sp!, {r4-r7,pc}
|
| 133 | +
|
| 134 | +renderchar_font:
|
| 135 | + .byte 0, 0, 0, 0, 0
|
| 136 | + .byte 0, 0, 95, 0, 0
|
| 137 | + .byte 0, 7, 0, 7, 0
|
| 138 | + .byte 20, 127, 20, 127, 20
|
| 139 | + .byte 36, 42, 127, 42, 18
|
| 140 | + .byte 35, 19, 8, 100, 98
|
| 141 | + .byte 54, 73, 85, 34, 80
|
| 142 | + .byte 5, 3, 0, 0, 0
|
| 143 | + .byte 28, 34, 65, 0, 0
|
| 144 | + .byte 0, 0, 65, 34, 28
|
| 145 | + .byte 20, 8, 62, 8, 20
|
| 146 | + .byte 8, 8, 62, 8, 8
|
| 147 | + .byte 0, -96, 96, 0, 0
|
| 148 | + .byte 8, 8, 8, 8, 8
|
| 149 | + .byte 0, 96, 96, 0, 0
|
| 150 | + .byte 32, 16, 8, 4, 2
|
| 151 | + .byte 62, 81, 73, 69, 62
|
| 152 | + .byte 0, 66, 127, 64, 0
|
| 153 | + .byte 66, 97, 81, 73, 70
|
| 154 | + .byte 33, 65, 69, 75, 49
|
| 155 | + .byte 24, 20, 18, 127, 16
|
| 156 | + .byte 39, 69, 69, 69, 57
|
| 157 | + .byte 60, 74, 73, 73, 48
|
| 158 | + .byte 1, 113, 9, 5, 3
|
| 159 | + .byte 54, 73, 73, 73, 54
|
| 160 | + .byte 6, 73, 73, 41, 30
|
| 161 | + .byte 0, 54, 54, 0, 0
|
| 162 | + .byte 0, 86, 54, 0, 0
|
| 163 | + .byte 8, 20, 34, 65, 0
|
| 164 | + .byte 20, 20, 20, 20, 20
|
| 165 | + .byte 0, 65, 34, 20, 8
|
| 166 | + .byte 2, 1, 81, 9, 6
|
| 167 | + .byte 50, 73, 121, 65, 62
|
| 168 | + .byte 124, 18, 17, 18, 124
|
| 169 | + .byte 127, 73, 73, 73, 62
|
| 170 | + .byte 62, 65, 65, 65, 34
|
| 171 | + .byte 127, 65, 65, 34, 28
|
| 172 | + .byte 127, 73, 73, 73, 65
|
| 173 | + .byte 127, 9, 9, 9, 1
|
| 174 | + .byte 62, 65, 73, 73, 58
|
| 175 | + .byte 127, 8, 8, 8, 127
|
| 176 | + .byte 0, 65, 127, 65, 0
|
| 177 | + .byte 32, 64, 65, 63, 1
|
| 178 | + .byte 127, 8, 20, 34, 65
|
| 179 | + .byte 127, 64, 64, 64, 64
|
| 180 | + .byte 127, 2, 12, 2, 127
|
| 181 | + .byte 127, 4, 8, 16, 127
|
| 182 | + .byte 62, 65, 65, 65, 62
|
| 183 | + .byte 127, 9, 9, 9, 6
|
| 184 | + .byte 62, 65, 81, 33, 94
|
| 185 | + .byte 127, 9, 25, 41, 70
|
| 186 | + .byte 38, 73, 73, 73, 50
|
| 187 | + .byte 1, 1, 127, 1, 1
|
| 188 | + .byte 63, 64, 64, 64, 63
|
| 189 | + .byte 31, 32, 64, 32, 31
|
| 190 | + .byte 127, 32, 24, 32, 127
|
| 191 | + .byte 99, 20, 8, 20, 99
|
| 192 | + .byte 3, 4, 120, 4, 3
|
| 193 | + .byte 97, 81, 73, 69, 67
|
| 194 | + .byte 0, 127, 65, 65, 0
|
| 195 | + .byte 2, 4, 8, 16, 32
|
| 196 | + .byte 0, 65, 65, 127, 0
|
| 197 | + .byte 4, 2, 1, 2, 4
|
| 198 | + .byte 64, 64, 64, 64, 64
|
| 199 | + .byte 1, 2, 4, 0, 0
|
| 200 | + .byte 32, 84, 84, 84, 120
|
| 201 | + .byte 127, 68, 68, 68, 56
|
| 202 | + .byte 56, 68, 68, 68, 40
|
| 203 | + .byte 56, 68, 68, 68, 127
|
| 204 | + .byte 56, 84, 84, 84, 24
|
| 205 | + .byte 8, 126, 9, 1, 2
|
| 206 | + .byte 8, 84, 84, 84, 60
|
| 207 | + .byte 127, 4, 4, 4, 120
|
| 208 | + .byte 0, 68, 125, 64, 0
|
| 209 | + .byte 32, 64, 64, 61, 0
|
| 210 | + .byte 127, 16, 40, 68, 0
|
| 211 | + .byte 0, 65, 127, 64, 0
|
| 212 | + .byte 124, 4, 24, 4, 120
|
| 213 | + .byte 124, 8, 4, 4, 120
|
| 214 | + .byte 56, 68, 68, 68, 56
|
| 215 | + .byte 124, 20, 20, 20, 24
|
| 216 | + .byte 8, 20, 20, 20, 124
|
| 217 | + .byte 124, 8, 4, 4, 8
|
| 218 | + .byte 72, 84, 84, 84, 32
|
| 219 | + .byte 4, 63, 68, 64, 32
|
| 220 | + .byte 60, 64, 64, 32, 124
|
| 221 | + .byte 28, 32, 64, 32, 28
|
| 222 | + .byte 60, 64, 56, 64, 60
|
| 223 | + .byte 68, 40, 16, 40, 68
|
| 224 | + .byte 12, 80, 80, 80, 60
|
| 225 | + .byte 68, 100, 84, 76, 68
|
| 226 | + .byte 0, 8, 54, 65, 0
|
| 227 | + .byte 0, 0, 119, 0, 0
|
| 228 | + .byte 0, 65, 54, 8, 0
|
| 229 | + .byte 2, 1, 2, 4, 2
|
| 230 | +.align 2
|
| 231 | +.size renderchar, .-renderchar
|
Index: embios/branches/4g_compat/lcdconsole.c |
— | — | @@ -0,0 +1,90 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#include "global.h"
|
| 26 | +#include "lcdconsole.h"
|
| 27 | +#include "util.h"
|
| 28 | +
|
| 29 | +
|
| 30 | +#define OFFSETX LCDCONSOLE_OFFSETX
|
| 31 | +#define OFFSETY LCDCONSOLE_OFFSETY
|
| 32 | +#define PIXELBYTES (LCD_BYTESPERPIXEL)
|
| 33 | +#define LINEBYTES (LCD_WIDTH * PIXELBYTES)
|
| 34 | +#define COLBYTES (FONT_WIDTH * PIXELBYTES)
|
| 35 | +#define ROWBYTES (FONT_HEIGHT * LINEBYTES)
|
| 36 | +#define OFFSETBYTES (LINEBYTES * OFFSETY + PIXELBYTES * OFFSETX)
|
| 37 | +
|
| 38 | +
|
| 39 | +static unsigned char framebuf[LCD_FRAMEBUFSIZE];
|
| 40 | +static unsigned int current_row;
|
| 41 | +static unsigned int current_col;
|
| 42 | +
|
| 43 | +
|
| 44 | +void lcdconsole_init()
|
| 45 | +{
|
| 46 | + memset(framebuf, -1, sizeof(framebuf));
|
| 47 | + current_row = 0;
|
| 48 | + current_col = -1;
|
| 49 | +}
|
| 50 | +
|
| 51 | +void lcdconsole_putc(char string, int fgcolor, int bgcolor)
|
| 52 | +{
|
| 53 | + if (string == '\r') return;
|
| 54 | + current_col++;
|
| 55 | + if (string == '\n')
|
| 56 | + {
|
| 57 | + current_col = -1;
|
| 58 | + current_row++;
|
| 59 | + return;
|
| 60 | + }
|
| 61 | + if (string == '\t')
|
| 62 | + {
|
| 63 | + current_col |= 3;
|
| 64 | + return;
|
| 65 | + }
|
| 66 | + if (current_col >= LCDCONSOLE_COLS)
|
| 67 | + {
|
| 68 | + current_col = 0;
|
| 69 | + current_row++;
|
| 70 | + }
|
| 71 | + if (current_row >= LCDCONSOLE_ROWS)
|
| 72 | + {
|
| 73 | + int offset = current_row - LCDCONSOLE_ROWS + 1;
|
| 74 | + memcpy(framebuf, &framebuf[ROWBYTES * offset], ROWBYTES * offset);
|
| 75 | + memset(&framebuf[sizeof(framebuf) - ROWBYTES * offset],
|
| 76 | + -1, ROWBYTES * offset);
|
| 77 | + }
|
| 78 | + renderchar(&framebuf[OFFSETBYTES + ROWBYTES * current_row
|
| 79 | + + COLBYTES * current_col],
|
| 80 | + fgcolor, bgcolor, string, LINEBYTES);
|
| 81 | +}
|
| 82 | +
|
| 83 | +void lcdconsole_puts(const char* string, int fgcolor, int bgcolor)
|
| 84 | +{
|
| 85 | + while (*string) lcdconsole_putc(*string++, fgcolor, bgcolor);
|
| 86 | +}
|
| 87 | +
|
| 88 | +void lcdconsole_update()
|
| 89 | +{
|
| 90 | + displaylcd(0, LCD_WIDTH - 1, 0, LCD_HEIGHT - 1, framebuf, 0);
|
| 91 | +}
|
Index: embios/branches/4g_compat/arm-support.S |
— | — | @@ -0,0 +1,706 @@ |
| 2 | +/***************************************************************************
|
| 3 | + * __________ __ ___.
|
| 4 | + * Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
| 5 | + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
| 6 | + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
| 7 | + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
| 8 | + * \/ \/ \/ \/ \/
|
| 9 | + * $Id$
|
| 10 | + *
|
| 11 | + * Copyright (C) 2008 by Jens Arnold
|
| 12 | + * Copyright (C) 2009 by Andrew Mahone
|
| 13 | + *
|
| 14 | + * Optimised replacements for libgcc functions
|
| 15 | + *
|
| 16 | + * Based on: libgcc routines for ARM cpu, additional algorithms from ARM System
|
| 17 | + * Developer's Guide
|
| 18 | + * Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
|
| 19 | + * Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005
|
| 20 | + * Free Software Foundation, Inc.
|
| 21 | + *
|
| 22 | + * This program is free software; you can redistribute it and/or
|
| 23 | + * modify it under the terms of the GNU General Public License
|
| 24 | + * as published by the Free Software Foundation; either version 2
|
| 25 | + * of the License, or (at your option) any later version.
|
| 26 | + *
|
| 27 | + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
| 28 | + * KIND, either express or implied.
|
| 29 | + *
|
| 30 | + ****************************************************************************/
|
| 31 | +
|
| 32 | +#define ASM_FILE
|
| 33 | +#include "global.h"
|
| 34 | +
|
| 35 | +.macro ARM_SDIV32_PRE numerator, divisor, sign
|
| 36 | + /* sign[31] = divisor sign */
|
| 37 | + ands \sign, \divisor, #1<<31
|
| 38 | + rsbeq \divisor, \divisor, #0
|
| 39 | + /* sign[31] = result sign, sign[0:30], C = numerator sign */
|
| 40 | + eors \sign, \sign, \numerator, asr #32
|
| 41 | + rsbcs \numerator, \numerator, #0
|
| 42 | +.endm
|
| 43 | +
|
| 44 | +.macro ARM_SDIV32_POST quotient, remainder, sign
|
| 45 | + movs \sign, \sign, lsl #1
|
| 46 | +.ifnc "", "\quotient"
|
| 47 | + rsbcs \quotient, \quotient, #0
|
| 48 | +.endif
|
| 49 | +.ifnc "", "\remainder"
|
| 50 | + rsbmi \remainder, \remainder, #0
|
| 51 | +.endif
|
| 52 | +.endm
|
| 53 | +
|
| 54 | +#if ARM_ARCH < 5
|
| 55 | +.macro ARMV4_UDIV32_BODY numerator, divisor, quotient, remainder, tmp, bits, div0label, return
|
| 56 | +.ifnc "", "\div0label"
|
| 57 | + rsbs \divisor, \divisor, #0
|
| 58 | + beq \div0label
|
| 59 | +.else
|
| 60 | + rsb \divisor, \divisor, #0
|
| 61 | +.endif
|
| 62 | + /* This SWAR divider requires a numerator less than 1<<31, because it must
|
| 63 | + be able to shift the remainder left at each step without shifting out
|
| 64 | + topmost bit. Since a shift might be needed for the aligned remainder to
|
| 65 | + exceed the divisor, the topmost bit must be unset at the start to avoid
|
| 66 | + this overflow case. The original numerator is saved so that the result
|
| 67 | + can be corrected after the reduced division completes. */
|
| 68 | + cmn \numerator, \divisor
|
| 69 | +.ifc "", "\quotient"
|
| 70 | +.ifc "\numerator", "\remainder"
|
| 71 | +.if \return
|
| 72 | + bxcc lr
|
| 73 | +.else
|
| 74 | + b 99f
|
| 75 | +.endif
|
| 76 | +.else
|
| 77 | + bcc 20f
|
| 78 | +.endif
|
| 79 | +.else
|
| 80 | + bcc 20f
|
| 81 | +.endif
|
| 82 | + movs \tmp, \numerator
|
| 83 | + movmi \numerator, \numerator, lsr #1
|
| 84 | + mov \bits, #30
|
| 85 | +.set shift, 16
|
| 86 | +.rept 5
|
| 87 | + cmn \divisor, \numerator, lsr #shift
|
| 88 | + subcs \bits, \bits, #shift
|
| 89 | + movcs \divisor, \divisor, lsl #shift
|
| 90 | +.set shift, shift >> 1
|
| 91 | +.endr
|
| 92 | + adds \numerator, \numerator, \divisor
|
| 93 | + subcc \numerator, \numerator, \divisor
|
| 94 | + add pc, pc, \bits, lsl #3
|
| 95 | + nop
|
| 96 | +.rept 30
|
| 97 | + adcs \numerator, \divisor, \numerator, lsl #1
|
| 98 | + subcc \numerator, \numerator, \divisor
|
| 99 | +.endr
|
| 100 | + adc \numerator, \numerator, \numerator
|
| 101 | + movs \tmp, \tmp, asr #1
|
| 102 | + rsb \bits, \bits, #31
|
| 103 | + bmi 10f
|
| 104 | +.ifc "", "\quotient"
|
| 105 | + mov \remainder, \numerator, lsr \bits
|
| 106 | +.else
|
| 107 | +.ifc "", "\remainder"
|
| 108 | + mov \divisor, \numerator, lsr \bits
|
| 109 | + eor \quotient, \numerator, \divisor, lsl \bits
|
| 110 | +.else
|
| 111 | + mov \remainder, \numerator, lsr \bits
|
| 112 | + eor \quotient, \numerator, \remainder, lsl \bits
|
| 113 | +.endif
|
| 114 | +.endif
|
| 115 | +.ifne \return
|
| 116 | + bx lr
|
| 117 | +.else
|
| 118 | + b 99f
|
| 119 | +.endif
|
| 120 | +10:
|
| 121 | + mov \tmp, \numerator, lsr \bits
|
| 122 | + eor \numerator, \numerator, \tmp, lsl \bits
|
| 123 | + sub \bits, \bits, #1
|
| 124 | + adc \tmp, \tmp, \tmp
|
| 125 | + adds \tmp, \tmp, \divisor, asr \bits
|
| 126 | +.ifnc "", "\quotient"
|
| 127 | + adc \quotient, \numerator, \numerator
|
| 128 | +.endif
|
| 129 | +.ifnc "", "\remainder"
|
| 130 | + subcc \remainder, \tmp, \divisor, asr \bits
|
| 131 | + movcs \remainder, \tmp
|
| 132 | +.endif
|
| 133 | +.ifne \return
|
| 134 | + bx lr
|
| 135 | +.else
|
| 136 | + b 99f
|
| 137 | +.endif
|
| 138 | +20:
|
| 139 | +.ifnc "", "\remainder"
|
| 140 | +.ifnc "\remainder", "\numerator"
|
| 141 | + mov \remainder, \numerator
|
| 142 | +.endif
|
| 143 | +.endif
|
| 144 | +.ifnc "", "\quotient"
|
| 145 | + mov \quotient, #0
|
| 146 | +.endif
|
| 147 | +.ifne \return
|
| 148 | + bx lr
|
| 149 | +.else
|
| 150 | +99:
|
| 151 | +.endif
|
| 152 | +.endm
|
| 153 | +
|
| 154 | +.macro ARMV4_SDIV32_BODY numerator, divisor, quotient, remainder, bits, sign, div0label, return
|
| 155 | + /* When this is wrapped for signed division, the wrapper code will handle
|
| 156 | + inverting the divisor, and also the zero divisor test. */
|
| 157 | + ARM_SDIV32_PRE \numerator, \divisor, \sign
|
| 158 | +.ifnc "", "\div0label"
|
| 159 | + tst \divisor, \divisor
|
| 160 | + beq \div0label
|
| 161 | +.endif
|
| 162 | + /* This SWAR divider requires a numerator less than 1<<31, because it must
|
| 163 | + be able to shift the remainder left at each step without shifting out
|
| 164 | + topmost bit. With signed inputs, whose absolute value may not exceed
|
| 165 | + 1<<31,this may be accomplished simply by subtracting the divisor before
|
| 166 | + beginning division, and adding 1 to the quotient. */
|
| 167 | + adds \numerator, \numerator, \divisor
|
| 168 | + bcc 20f
|
| 169 | + mov \bits, #30
|
| 170 | +.set shift, 16
|
| 171 | +.rept 5
|
| 172 | + cmn \divisor, \numerator, lsr #shift
|
| 173 | + subcs \bits, \bits, #shift
|
| 174 | + movcs \divisor, \divisor, lsl #shift
|
| 175 | +.set shift, shift >> 1
|
| 176 | +.endr
|
| 177 | + adds \numerator, \numerator, \divisor
|
| 178 | + subcc \numerator, \numerator, \divisor
|
| 179 | + add pc, pc, \bits, lsl #3
|
| 180 | + nop
|
| 181 | +.rept 30
|
| 182 | + adcs \numerator, \divisor, \numerator, lsl #1
|
| 183 | + subcc \numerator, \numerator, \divisor
|
| 184 | +.endr
|
| 185 | + rsb \bits, \bits, #31
|
| 186 | + adc \numerator, \numerator, \numerator
|
| 187 | +.ifc "", "\quotient"
|
| 188 | + mov \remainder, \numerator, lsr \bits
|
| 189 | +.else
|
| 190 | +.ifc "", "\remainder"
|
| 191 | + mov \divisor, \numerator, lsr \bits
|
| 192 | + add \numerator, \numerator, #1
|
| 193 | + sub \quotient, \numerator, \divisor, lsl \bits
|
| 194 | +.else
|
| 195 | + mov \remainder, \numerator, lsr \bits
|
| 196 | + add \numerator, \numerator, #1
|
| 197 | + sub \quotient, \numerator, \remainder, lsl \bits
|
| 198 | +.endif
|
| 199 | +.endif
|
| 200 | +.ifne \return
|
| 201 | + ARM_SDIV32_POST \quotient, \remainder, \sign
|
| 202 | + bx lr
|
| 203 | +.else
|
| 204 | + b 99f
|
| 205 | +.endif
|
| 206 | +20:
|
| 207 | +.ifnc "", "\remainder"
|
| 208 | + sub \remainder, \numerator, \divisor
|
| 209 | +.endif
|
| 210 | +.ifnc "", "\quotient"
|
| 211 | + mov \quotient, #0
|
| 212 | +.endif
|
| 213 | +.ifne \return
|
| 214 | + ARM_SDIV32_POST "", \remainder, \sign
|
| 215 | + bx lr
|
| 216 | +.else
|
| 217 | +99:
|
| 218 | + ARM_SDIV32_POST \quotient, \remainder, \sign
|
| 219 | +.endif
|
| 220 | +.endm
|
| 221 | +
|
| 222 | +#else
|
| 223 | +.macro ARMV5_UDIV32_BODY numerator, divisor, quotient, remainder, bits, inv, neg, div0label, return
|
| 224 | + cmp \numerator, \divisor
|
| 225 | + clz \bits, \divisor
|
| 226 | + bcc 30f
|
| 227 | + mov \inv, \divisor, lsl \bits
|
| 228 | + add \neg, pc, \inv, lsr #25
|
| 229 | + /* Test whether divisor is 2^N */
|
| 230 | + cmp \inv, #1<<31
|
| 231 | + /* Load approximate reciprocal */
|
| 232 | + ldrhib \inv, [\neg, #.L_udiv_est_table-.-64]
|
| 233 | + bls 20f
|
| 234 | + subs \bits, \bits, #7
|
| 235 | + rsb \neg, \divisor, #0
|
| 236 | + /* Scale approximate reciprocal, or else branch to large-divisor path */
|
| 237 | + movpl \divisor, \inv, lsl \bits
|
| 238 | + bmi 10f
|
| 239 | + /* Newton-Raphson iteration to improve reciprocal accuracy */
|
| 240 | + mul \inv, \divisor, \neg
|
| 241 | + smlawt \divisor, \divisor, \inv, \divisor
|
| 242 | + mul \inv, \divisor, \neg
|
| 243 | + /* Complete N-R math and produce approximate quotient. Use smmla/smmul on
|
| 244 | + ARMv6. */
|
| 245 | +#if ARM_ARCH >= 6
|
| 246 | + tst \numerator, \numerator
|
| 247 | + smmla \divisor, \divisor, \inv, \divisor
|
| 248 | + /* Branch to large-numerator handler, or else use smmul if sign bit is not
|
| 249 | + set. This wins on average with random numerators, and should be no
|
| 250 | + slower than using umull for small numerator, even if prediction fails.
|
| 251 | + */
|
| 252 | + bmi 40f
|
| 253 | + smmul \inv, \numerator, \divisor
|
| 254 | +#else
|
| 255 | + /* ARMv5e lacks smmul, so always uses umull. */
|
| 256 | + mov \bits, #0
|
| 257 | + smlal \bits, \divisor, \inv, \divisor
|
| 258 | + umull \bits, \inv, \numerator, \divisor
|
| 259 | +#endif
|
| 260 | + /* Calculate remainder and correct result. */
|
| 261 | + add \numerator, \numerator, \neg
|
| 262 | +.ifnc "", "\remainder"
|
| 263 | + mla \remainder, \inv, \neg, \numerator
|
| 264 | +.ifnc "", "\quotient"
|
| 265 | + mov \quotient, \inv
|
| 266 | + cmn \remainder, \neg
|
| 267 | + subcs \remainder, \remainder, \neg
|
| 268 | + addpl \remainder, \remainder, \neg, lsl #1
|
| 269 | + addcc \quotient, \quotient, #1
|
| 270 | + addpl \quotient, \quotient, #2
|
| 271 | +.else
|
| 272 | + cmn \remainder, \neg
|
| 273 | + subcs \remainder, \remainder, \neg
|
| 274 | + addpl \remainder, \remainder, \neg, lsl #1
|
| 275 | +.endif
|
| 276 | +.else
|
| 277 | + mla \divisor, \inv, \neg, \numerator
|
| 278 | + mov \quotient, \inv
|
| 279 | + cmn \divisor, \neg
|
| 280 | + addcc \quotient, \quotient, #1
|
| 281 | + addpl \quotient, \quotient, #2
|
| 282 | +.endif
|
| 283 | +.if \return
|
| 284 | + bx lr
|
| 285 | +.else
|
| 286 | + b 99f
|
| 287 | +.endif
|
| 288 | +10:
|
| 289 | + /* Very large divisors can be handled without further improving the
|
| 290 | + reciprocal. First the reciprocal must be reduced to ensure that it
|
| 291 | + underestimates the correct value. */
|
| 292 | + rsb \bits, \bits, #0
|
| 293 | + sub \inv, \inv, #4
|
| 294 | + mov \divisor, \inv, lsr \bits
|
| 295 | + /* Calculate approximate quotient and remainder */
|
| 296 | + umull \bits, \inv, \numerator, \divisor
|
| 297 | + /* Correct quotient and remainder */
|
| 298 | +.ifnc "", "\remainder"
|
| 299 | + mla \remainder, \inv, \neg, \numerator
|
| 300 | +.ifnc "", "\quotient"
|
| 301 | + mov \quotient, \inv
|
| 302 | + cmn \neg, \remainder, lsr #1
|
| 303 | + addcs \remainder, \remainder, \neg, lsl #1
|
| 304 | + addcs \quotient, \quotient, #2
|
| 305 | + cmn \neg, \remainder
|
| 306 | + addcs \remainder, \remainder, \neg
|
| 307 | + addcs \quotient, \quotient, #1
|
| 308 | +.else
|
| 309 | + cmn \neg, \remainder, lsr #1
|
| 310 | + addcs \remainder, \remainder, \neg, lsl #1
|
| 311 | + cmn \neg, \remainder
|
| 312 | + addcs \remainder, \remainder, \neg
|
| 313 | +.endif
|
| 314 | +.else
|
| 315 | + mla \divisor, \inv, \neg, \numerator
|
| 316 | + mov \quotient, \inv
|
| 317 | + cmn \neg, \divisor, lsr #1
|
| 318 | + addcs \divisor, \divisor, \neg, lsl #1
|
| 319 | + addcs \quotient, \quotient, #2
|
| 320 | + cmn \neg, \divisor
|
| 321 | + addcs \quotient, \quotient, #1
|
| 322 | +.endif
|
| 323 | +.if \return
|
| 324 | + bx lr
|
| 325 | +.else
|
| 326 | + b 99f
|
| 327 | +.endif
|
| 328 | +20:
|
| 329 | + /* Handle division by powers of two by shifting right. Mod is handled
|
| 330 | + by using divisor-1 as a bitmask. */
|
| 331 | +.ifnc "", "\remainder"
|
| 332 | +.ifnc "", "\div0label"
|
| 333 | + bne \div0label
|
| 334 | +.endif
|
| 335 | +.ifnc "", "\quotient"
|
| 336 | + sub \divisor, \divisor, #1
|
| 337 | + rsb \bits, \bits, #31
|
| 338 | + and \remainder, \numerator, \divisor
|
| 339 | + mov \quotient, \numerator, lsr \bits
|
| 340 | +.else
|
| 341 | + sub \divisor, \divisor, #1
|
| 342 | + and \remainder, \numerator, \divisor
|
| 343 | +.endif
|
| 344 | +.else
|
| 345 | + rsb \bits, \bits, #31
|
| 346 | +.ifnc "", "\div0label"
|
| 347 | + bne \div0label
|
| 348 | +.endif
|
| 349 | + mov \quotient, \numerator, lsr \bits
|
| 350 | +.endif
|
| 351 | +.if \return
|
| 352 | + bx lr
|
| 353 | +.else
|
| 354 | + b 99f
|
| 355 | +.endif
|
| 356 | +30:
|
| 357 | + /* Handle numerator < divisor - quotient is zero, remainder is numerator,
|
| 358 | + which must be restored to its original value on ARMv6. */
|
| 359 | +.ifnc "", "\remainder"
|
| 360 | + mov \remainder, \numerator
|
| 361 | +.endif
|
| 362 | +.ifnc "", "\quotient"
|
| 363 | + mov \quotient, #0
|
| 364 | +.endif
|
| 365 | +.if \return
|
| 366 | + bx lr
|
| 367 | +.endif
|
| 368 | +#if ARM_ARCH >= 6
|
| 369 | +40:
|
| 370 | + /* Handle large (sign bit set) numerators. Works exactly as the ARMv5e code
|
| 371 | + above 10:. */
|
| 372 | + umull \bits, \inv, \numerator, \divisor
|
| 373 | + add \numerator, \numerator, \neg
|
| 374 | +.ifnc "", "\remainder"
|
| 375 | + mla \remainder, \inv, \neg, \numerator
|
| 376 | +.ifnc "", "\quotient"
|
| 377 | + mla \remainder, \inv, \neg, \numerator
|
| 378 | + mov \quotient, \inv
|
| 379 | + cmn \remainder, \neg
|
| 380 | + subcs \remainder, \remainder, \neg
|
| 381 | + addpl \remainder, \remainder, \neg, lsl #1
|
| 382 | + addcc \quotient, \quotient, #1
|
| 383 | + addpl \quotient, \quotient, #2
|
| 384 | +.else
|
| 385 | + cmn \remainder, \neg
|
| 386 | + subcs \remainder, \remainder, \neg
|
| 387 | + addpl \remainder, \remainder, \neg, lsl #1
|
| 388 | +.endif
|
| 389 | +.else
|
| 390 | + mla \divisor, \inv, \neg, \numerator
|
| 391 | + mov \quotient, \inv
|
| 392 | + cmn \divisor, \neg
|
| 393 | + addcc \quotient, \quotient, #1
|
| 394 | + addpl \quotient, \quotient, #2
|
| 395 | +.endif
|
| 396 | +.if \return
|
| 397 | + bx lr
|
| 398 | +.else
|
| 399 | + b 99f
|
| 400 | +.endif
|
| 401 | +#endif
|
| 402 | +99:
|
| 403 | +.endm
|
| 404 | +
|
| 405 | +.macro ARMV5_SDIV32_BODY numerator, divisor, quotient, remainder, bits, inv, neg, sign, div0label, return
|
| 406 | + /* sign[31] = divisor sign */
|
| 407 | + ands \sign, \divisor, #1<<31
|
| 408 | + rsbne \divisor, \divisor, #0
|
| 409 | + /* sign[31] = result sign, sign[0:30], C = numerator sign */
|
| 410 | + eors \sign, \sign, \numerator, asr #32
|
| 411 | + clz \bits, \divisor
|
| 412 | + rsbcs \numerator, \numerator, #0
|
| 413 | + /* On ARMv6, subtract divisor before performing division, which ensures
|
| 414 | + numerator sign bit is clear and smmul may be used in place of umull. The
|
| 415 | + fixup for the results can be fit entirely into existing delay slots on
|
| 416 | + the main division paths. It costs 1c in the num<div path if the
|
| 417 | + the remainder is to be produced in the numerator's register, and 1c in
|
| 418 | + the power-of-2-divisor path only if producing both remainder and
|
| 419 | + quotient. */
|
| 420 | +#if ARM_ARCH >= 6
|
| 421 | + subs \numerator, \numerator, \divisor
|
| 422 | +#else
|
| 423 | + cmp \numerator, \divisor
|
| 424 | +#endif
|
| 425 | + movcs \inv, \divisor, lsl \bits
|
| 426 | + bcc 30f
|
| 427 | + /* Test whether divisor is 2^N */
|
| 428 | + cmp \inv, #1<<31
|
| 429 | + add \inv, pc, \inv, lsr #25
|
| 430 | + bls 20f
|
| 431 | + /* Load approximate reciprocal */
|
| 432 | + ldrb \inv, [\inv, #.L_udiv_est_table-.-64]
|
| 433 | + subs \bits, \bits, #7
|
| 434 | + rsb \neg, \divisor, #0
|
| 435 | + /* Scale approximate reciprocal, or else branch to large-divisor path */
|
| 436 | + movpl \divisor, \inv, lsl \bits
|
| 437 | + bmi 10f
|
| 438 | + /* Newton-Raphson iteration to improve reciprocal accuracy */
|
| 439 | + mul \inv, \divisor, \neg
|
| 440 | + smlawt \divisor, \divisor, \inv, \divisor
|
| 441 | + mul \inv, \divisor, \neg
|
| 442 | + /* Complete N-R math and produce approximate quotient. Use smmla/smmul on
|
| 443 | + ARMv6. */
|
| 444 | +#if ARM_ARCH >= 6
|
| 445 | + smmla \divisor, \divisor, \inv, \divisor
|
| 446 | + smmul \inv, \numerator, \divisor
|
| 447 | +#else
|
| 448 | + mov \bits, #0
|
| 449 | + smlal \bits, \divisor, \inv, \divisor
|
| 450 | + umull \bits, \inv, \numerator, \divisor
|
| 451 | +#endif
|
| 452 | + /* Calculate remainder and correct quotient. */
|
| 453 | + add \numerator, \numerator, \neg
|
| 454 | +.ifnc "", "\remainder"
|
| 455 | + mla \remainder, \inv, \neg, \numerator
|
| 456 | +.ifnc "", "\quotient"
|
| 457 | +#if ARM_ARCH >= 6
|
| 458 | + add \quotient, \inv, #1
|
| 459 | +#else
|
| 460 | + mov \quotient, \inv
|
| 461 | +#endif
|
| 462 | + cmn \remainder, \neg
|
| 463 | + subcs \remainder, \remainder, \neg
|
| 464 | + addpl \remainder, \remainder, \neg, lsl #1
|
| 465 | + addcc \quotient, \quotient, #1
|
| 466 | + addpl \quotient, \quotient, #2
|
| 467 | +.else
|
| 468 | + cmn \remainder, \neg
|
| 469 | + subcs \remainder, \remainder, \neg
|
| 470 | + addpl \remainder, \remainder, \neg, lsl #1
|
| 471 | +.endif
|
| 472 | +.else
|
| 473 | + mla \divisor, \inv, \neg, \numerator
|
| 474 | +#if ARM_ARCH >= 6
|
| 475 | + add \quotient, \inv, #1
|
| 476 | +#else
|
| 477 | + mov \quotient, \inv
|
| 478 | +#endif
|
| 479 | + cmn \divisor, \neg
|
| 480 | + addcc \quotient, \quotient, #1
|
| 481 | + addpl \quotient, \quotient, #2
|
| 482 | +.endif
|
| 483 | + ARM_SDIV32_POST \quotient, \remainder, \sign
|
| 484 | +.ifnc "", "\return"
|
| 485 | + \return
|
| 486 | +.else
|
| 487 | + b 99f
|
| 488 | +.endif
|
| 489 | +10:
|
| 490 | + /* Very large divisors can be handled without further improving the
|
| 491 | + reciprocal. First the reciprocal must be reduced to ensure that it
|
| 492 | + underestimates the correct value. */
|
| 493 | + rsb \bits, \bits, #0
|
| 494 | + sub \inv, \inv, #4
|
| 495 | + mov \divisor, \inv, lsr \bits
|
| 496 | + /* Calculate approximate quotient and remainder */
|
| 497 | +#if ARM_ARCH >= 6
|
| 498 | + smmul \inv, \numerator, \divisor
|
| 499 | +#else
|
| 500 | + umull \bits, \inv, \numerator, \divisor
|
| 501 | +#endif
|
| 502 | + /* Correct quotient and remainder */
|
| 503 | +.ifnc "", "\remainder"
|
| 504 | + mla \remainder, \inv, \neg, \numerator
|
| 505 | +.ifnc "", "\quotient"
|
| 506 | +#if ARM_ARCH >= 6
|
| 507 | + add \quotient, \inv, #1
|
| 508 | +#else
|
| 509 | + mov \quotient, \inv
|
| 510 | +#endif
|
| 511 | + cmn \neg, \remainder, lsr #1
|
| 512 | + addcs \remainder, \remainder, \neg, lsl #1
|
| 513 | + addcs \quotient, \quotient, #2
|
| 514 | + cmn \neg, \remainder
|
| 515 | + addcs \remainder, \remainder, \neg
|
| 516 | + addcs \quotient, \quotient, #1
|
| 517 | +.else
|
| 518 | + cmn \neg, \remainder, lsr #1
|
| 519 | + addcs \remainder, \remainder, \neg, lsl #1
|
| 520 | + cmn \neg, \remainder
|
| 521 | + addcs \remainder, \remainder, \neg
|
| 522 | +.endif
|
| 523 | +.else
|
| 524 | + mla \divisor, \inv, \neg, \numerator
|
| 525 | +#if ARM_ARCH >= 6
|
| 526 | + add \quotient, \inv, #1
|
| 527 | +#else
|
| 528 | + mov \quotient, \inv
|
| 529 | +#endif
|
| 530 | + cmn \neg, \divisor, lsr #1
|
| 531 | + addcs \divisor, \divisor, \neg, lsl #1
|
| 532 | + addcs \quotient, \quotient, #2
|
| 533 | + cmn \neg, \divisor
|
| 534 | + addcs \quotient, \quotient, #1
|
| 535 | +.endif
|
| 536 | + ARM_SDIV32_POST \quotient, \remainder, \sign
|
| 537 | +.ifnc "", "\return"
|
| 538 | + \return
|
| 539 | +.else
|
| 540 | + b 99f
|
| 541 | +.endif
|
| 542 | +20:
|
| 543 | + /* Handle division by powers of two by shifting right. Mod is handled
|
| 544 | + by using divisor-1 as a bitmask. */
|
| 545 | +.ifnc "", "\div0label"
|
| 546 | + bne \div0label
|
| 547 | +.endif
|
| 548 | +.ifnc "", "\remainder"
|
| 549 | +.ifnc "", "\quotient"
|
| 550 | + rsb \bits, \bits, #31
|
| 551 | +#if ARM_ARCH >= 6
|
| 552 | + add \numerator, \numerator, \divisor
|
| 553 | +#endif
|
| 554 | + sub \divisor, \divisor, #1
|
| 555 | + and \remainder, \numerator, \divisor
|
| 556 | + mov \quotient, \numerator, lsr \bits
|
| 557 | +.else
|
| 558 | + sub \divisor, \divisor, #1
|
| 559 | + and \remainder, \numerator, \divisor
|
| 560 | +.endif
|
| 561 | +.else
|
| 562 | + rsb \bits, \bits, #31
|
| 563 | +#if ARM_ARCH >= 6
|
| 564 | + add \numerator, \numerator, \divisor
|
| 565 | +#endif
|
| 566 | + mov \quotient, \numerator, lsr \bits
|
| 567 | +.endif
|
| 568 | + ARM_SDIV32_POST \quotient, \remainder, \sign
|
| 569 | +.ifnc "", "\return"
|
| 570 | + \return
|
| 571 | +.else
|
| 572 | + b 99f
|
| 573 | +.endif
|
| 574 | +30:
|
| 575 | + /* Handle numerator < divisor - quotient is zero, remainder is numerator,
|
| 576 | + which must be restored to its original value on ARMv6. */
|
| 577 | +.ifnc "", "\remainder"
|
| 578 | +#if ARM_ARCH >= 6
|
| 579 | + add \remainder, \numerator, \divisor
|
| 580 | +#else
|
| 581 | +.ifnc "\remainder", "\numerator"
|
| 582 | + mov \remainder, \numerator
|
| 583 | +.endif
|
| 584 | +#endif
|
| 585 | +.endif
|
| 586 | +.ifnc "", "\quotient"
|
| 587 | + mov \quotient, #0
|
| 588 | +.endif
|
| 589 | +.ifnc "", "\remainder"
|
| 590 | + ARM_SDIV32_POST "", \remainder, \sign
|
| 591 | +.endif
|
| 592 | +.ifnc "", "\return"
|
| 593 | + \return
|
| 594 | +.endif
|
| 595 | +99:
|
| 596 | +.endm
|
| 597 | +#endif
|
| 598 | +
|
| 599 | + .section .text.__div0_wrap_s
|
| 600 | +__div0_wrap_s:
|
| 601 | + sub sp, sp, #4
|
| 602 | + b __div0
|
| 603 | + .size __div0_wrap_s, . - __div0_wrap_s
|
| 604 | +
|
| 605 | + .section .text.__div0_wrap
|
| 606 | +__div0_wrap:
|
| 607 | + str lr, [sp, #-4]!
|
| 608 | + b __div0
|
| 609 | + .size __div0_wrap, . - __div0_wrap
|
| 610 | +
|
| 611 | +#ifndef __ARM_EABI__
|
| 612 | + .global __divsi3
|
| 613 | + .type __divsi3,%function
|
| 614 | + .global __udivsi3
|
| 615 | + .type __udivsi3,%function
|
| 616 | + .global __udivsi3
|
| 617 | + .type __udivsi3,%function
|
| 618 | +#else
|
| 619 | +/* The div+mod averagess a fraction of a cycle worse for signed values, and
|
| 620 | + slightly better for unsigned, so just alias div to divmod. */
|
| 621 | + .global __aeabi_uidivmod
|
| 622 | + .type __aeabi_uidivmod,%function
|
| 623 | + .global __aeabi_uidiv
|
| 624 | + .type __aeabi_uidiv,%function
|
| 625 | + .set __aeabi_uidiv,__aeabi_uidivmod
|
| 626 | + .global __aeabi_idivmod
|
| 627 | + .type __aeabi_idivmod,%function
|
| 628 | + .global __aeabi_idiv
|
| 629 | + .type __aeabi_idiv,%function
|
| 630 | + .set __aeabi_idiv,__aeabi_idivmod
|
| 631 | +#endif
|
| 632 | +
|
| 633 | +
|
| 634 | +#if ARM_ARCH < 5
|
| 635 | + .section .text.__clzsi2
|
| 636 | + .global __clzsi2
|
| 637 | + .type __clzsi2, %function
|
| 638 | +
|
| 639 | +__clzsi2:
|
| 640 | + orr r0, r0, r0, lsr #8
|
| 641 | + orr r0, r0, r0, lsr #4
|
| 642 | + orr r0, r0, r0, lsr #2
|
| 643 | + orr r0, r0, r0, lsr #1
|
| 644 | + bic r0, r0, r0, lsr #16
|
| 645 | + rsb r0, r0, r0, lsl #14
|
| 646 | + rsb r0, r0, r0, lsl #11
|
| 647 | + rsb r0, r0, r0, lsl #9
|
| 648 | + ldrb r0, [pc, r0, lsr #26]
|
| 649 | + bx lr
|
| 650 | + .byte 32, 20, 19, 0, 0, 18, 0, 7, 10, 17, 0, 0, 14, 0, 6, 0
|
| 651 | + .byte 0, 9, 0, 16, 0, 0, 1, 26, 0, 13, 0, 0, 24, 5, 0, 0
|
| 652 | + .byte 0, 21, 0, 8, 11, 0, 15, 0, 0, 0, 0, 2, 27, 0, 25, 0
|
| 653 | + .byte 22, 0, 12, 0, 0, 3, 28, 0, 23, 0, 4, 29, 0, 0, 30, 31
|
| 654 | + .size __clzsi2, .-__clzsi2
|
| 655 | +
|
| 656 | + .section .text.__divisionhelpers
|
| 657 | +#ifndef __ARM_EABI__
|
| 658 | +__udivsi3:
|
| 659 | + ARMV4_UDIV32_BODY r0, r1, r0, "", r2, r3, __div0_wrap, 1
|
| 660 | + .size __udivsi3, . - __udivsi3
|
| 661 | +
|
| 662 | +__divsi3:
|
| 663 | + ARMV4_SDIV32_BODY r0, r1, r0, "", r2, r3, __div0_wrap, 1
|
| 664 | + .size __divsi3, . - __divsi3
|
| 665 | +
|
| 666 | +#else
|
| 667 | +__aeabi_uidivmod:
|
| 668 | + ARMV4_UDIV32_BODY r0, r1, r0, r1, r2, r3, __div0_wrap, 1
|
| 669 | + .size __aeabi_uidivmod, . - __aeabi_uidivmo
|
| 670 | +
|
| 671 | +__aeabi_idivmod:
|
| 672 | + ARMV4_SDIV32_BODY r0, r1, r0, r1, r2, r3, __div0_wrap, 1
|
| 673 | + .size __aeabi_idivmod, . - __aeabi_idivmod
|
| 674 | +#endif
|
| 675 | +
|
| 676 | +#else
|
| 677 | +#ifndef __ARM_EABI__
|
| 678 | +__udivsi3:
|
| 679 | + ARMV5_UDIV32_BODY r0, r1, r0, "", r2, r3, ip, __div0_wrap, 1
|
| 680 | + .size __udivsi3, . - __udivsi3
|
| 681 | +
|
| 682 | +__divsi3:
|
| 683 | + str lr, [sp, #-4]
|
| 684 | + ARMV5_SDIV32_BODY r0, r1, r0, "", r2, lr, ip, r3, __div0_wrap_s, "ldr pc, [sp, #-4]"
|
| 685 | + .size __divsi3, . - __divsi3
|
| 686 | +
|
| 687 | +#else
|
| 688 | +__aeabi_uidivmod:
|
| 689 | + ARMV5_UDIV32_BODY r0, r1, r0, r1, r2, r3, ip, __div0_wrap, 1
|
| 690 | + .size __aeabi_uidivmod, . - __aeabi_uidivmo
|
| 691 | +
|
| 692 | +__aeabi_idivmod:
|
| 693 | + str lr, [sp, #-4]
|
| 694 | + ARMV5_SDIV32_BODY r0, r1, r0, r1, r2, lr, ip, r3, __div0_wrap_s, "ldr pc, [sp, #-4]"
|
| 695 | + .size __aeabi_idivmod, . - __aeabi_idivmod
|
| 696 | +#endif
|
| 697 | +
|
| 698 | +.L_udiv_est_table:
|
| 699 | + .byte 0xff, 0xfc, 0xf8, 0xf4, 0xf0, 0xed, 0xea, 0xe6
|
| 700 | + .byte 0xe3, 0xe0, 0xdd, 0xda, 0xd7, 0xd4, 0xd2, 0xcf
|
| 701 | + .byte 0xcc, 0xca, 0xc7, 0xc5, 0xc3, 0xc0, 0xbe, 0xbc
|
| 702 | + .byte 0xba, 0xb8, 0xb6, 0xb4, 0xb2, 0xb0, 0xae, 0xac
|
| 703 | + .byte 0xaa, 0xa8, 0xa7, 0xa5, 0xa3, 0xa2, 0xa0, 0x9f
|
| 704 | + .byte 0x9d, 0x9c, 0x9a, 0x99, 0x97, 0x96, 0x94, 0x93
|
| 705 | + .byte 0x92, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8a, 0x89
|
| 706 | + .byte 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81
|
| 707 | +#endif
|
Index: embios/branches/4g_compat/panic.h |
— | — | @@ -0,0 +1,35 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __PANIC_H__
|
| 26 | +#define __PANIC_H__
|
| 27 | +
|
| 28 | +
|
| 29 | +#include "global.h"
|
| 30 | +
|
| 31 | +
|
| 32 | +void panic(const char* string) ICODE_ATTR;
|
| 33 | +void panicf(const char* string, ...) ICODE_ATTR;
|
| 34 | +
|
| 35 | +
|
| 36 | +#endif
|
Index: embios/branches/4g_compat/console.c |
— | — | @@ -0,0 +1,89 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#include "global.h"
|
| 26 | +#include "console.h"
|
| 27 | +#include "lcdconsole.h"
|
| 28 | +#include "format.h"
|
| 29 | +#include <stdio.h>
|
| 30 | +#include <stdarg.h>
|
| 31 | +#include <stdbool.h>
|
| 32 | +#include <limits.h>
|
| 33 | +
|
| 34 | +
|
| 35 | +struct for_cprintf
|
| 36 | +{
|
| 37 | + unsigned int consoles;
|
| 38 | + size_t bytes;
|
| 39 | +};
|
| 40 | +
|
| 41 | +
|
| 42 | +static int cprfunc(void* ptr, unsigned char letter)
|
| 43 | +{
|
| 44 | + struct for_cprintf* pr = (struct for_cprintf*)ptr;
|
| 45 | + cputc(pr->consoles, letter);
|
| 46 | + pr->bytes++;
|
| 47 | + return true;
|
| 48 | +}
|
| 49 | +
|
| 50 | +int cprintf(unsigned int consoles, const char* fmt, ...)
|
| 51 | +{
|
| 52 | + va_list ap;
|
| 53 | + struct for_cprintf pr;
|
| 54 | +
|
| 55 | + pr.consoles = consoles;
|
| 56 | + pr.bytes = 0;
|
| 57 | +
|
| 58 | + va_start(ap, fmt);
|
| 59 | + format(cprfunc, &pr, fmt, ap);
|
| 60 | + va_end(ap);
|
| 61 | +
|
| 62 | + return pr.bytes;
|
| 63 | +}
|
| 64 | +
|
| 65 | +int cvprintf(unsigned int consoles, const char* fmt, va_list ap)
|
| 66 | +{
|
| 67 | + struct for_cprintf pr;
|
| 68 | +
|
| 69 | + pr.consoles = consoles;
|
| 70 | + pr.bytes = 0;
|
| 71 | +
|
| 72 | + format(cprfunc, &pr, fmt, ap);
|
| 73 | +
|
| 74 | + return pr.bytes;
|
| 75 | +}
|
| 76 | +
|
| 77 | +void cputc(unsigned int consoles, char string)
|
| 78 | +{
|
| 79 | + if (consoles & 1) lcdconsole_putc(string, 0, -1);
|
| 80 | +}
|
| 81 | +
|
| 82 | +void cputs(unsigned int consoles, const char* string)
|
| 83 | +{
|
| 84 | + if (consoles & 1) lcdconsole_puts(string, 0, -1);
|
| 85 | +}
|
| 86 | +
|
| 87 | +void cflush(unsigned int consoles)
|
| 88 | +{
|
| 89 | + if (consoles & 1) lcdconsole_update();
|
| 90 | +}
|
Index: embios/branches/4g_compat/ucl.S |
— | — | @@ -0,0 +1,135 @@ |
| 2 | +/* arm_nrv2e_d8.S -- ARM decompressor for NRV2E
|
| 3 | +
|
| 4 | + This file is part of the UPX executable compressor.
|
| 5 | +
|
| 6 | + Copyright (C) 1996-2008 Markus Franz Xaver Johannes Oberhumer
|
| 7 | + Copyright (C) 1996-2008 Laszlo Molnar
|
| 8 | + Copyright (C) 2000-2008 John F. Reiser
|
| 9 | + All Rights Reserved.
|
| 10 | +
|
| 11 | + UPX and the UCL library are free software; you can redistribute them
|
| 12 | + and/or modify them under the terms of the GNU General Public License as
|
| 13 | + published by the Free Software Foundation; either version 2 of
|
| 14 | + the License, or (at your option) any later version.
|
| 15 | +
|
| 16 | + This program is distributed in the hope that it will be useful,
|
| 17 | + but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 18 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| 19 | + GNU General Public License for more details.
|
| 20 | +
|
| 21 | + You should have received a copy of the GNU General Public License
|
| 22 | + along with this program; see the file COPYING.
|
| 23 | + If not, write to the Free Software Foundation, Inc.,
|
| 24 | + 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
| 25 | +
|
| 26 | + Markus F.X.J. Oberhumer Laszlo Molnar
|
| 27 | + <markus@oberhumer.com> <ml1050@users.sourceforge.net>
|
| 28 | +
|
| 29 | + John F. Reiser
|
| 30 | + <jreiser@users.sourceforge.net>
|
| 31 | +*/
|
| 32 | +
|
| 33 | +#define src r0
|
| 34 | +#define len r1 /* overlaps 'cnt' */
|
| 35 | +#define dst r2
|
| 36 | +#define tmp r3
|
| 37 | +#define bits r4
|
| 38 | +#define off r5
|
| 39 | +#define wrnk r6 /* 0x500 M2_MAX_OFFSET before "wrinkle" */
|
| 40 | +#define srclim r7
|
| 41 | +
|
| 42 | +#define cnt r1 /* overlaps 'len' while reading an offset */
|
| 43 | +
|
| 44 | +/* "mov lr,pc; bxx ..." implements conditional subroutine call */
|
| 45 | +#define GETBIT add bits,bits; mov lr,pc; beq get1_n2e
|
| 46 | +
|
| 47 | +#define getnextb(reg) GETBIT; adc reg,reg
|
| 48 | +#define jnextb0 GETBIT; bcc
|
| 49 | +#define jnextb1 GETBIT; bcs
|
| 50 | +
|
| 51 | +.section .icode.ucl_decompress, "ax", %progbits
|
| 52 | +.align 2
|
| 53 | +ucl_decompress: .globl ucl_nrv2e_decompress_8 @ ARM mode
|
| 54 | + .type ucl_nrv2e_decompress_8, %function
|
| 55 | +/* error = (*)(char const *src, int len_src, char *dst, int *plen_dst)
|
| 56 | + Actual decompressed length is stored through plen_dst.
|
| 57 | +*/
|
| 58 | + adr r12,1+.thumb_nrv2e_d8; bx r12 @ enter THUMB mode
|
| 59 | + .code 16 @ THUMB mode
|
| 60 | + .thumb_func
|
| 61 | +
|
| 62 | +.thumb_nrv2e_d8:
|
| 63 | + push {r2,r3,r4,r5,r6,r7,lr}
|
| 64 | + add srclim,len,src @ srclim= eof_src;
|
| 65 | + mov bits,#1; neg off,bits @ off= -1 initial condition
|
| 66 | + lsl bits,#31 @ 1<<31: refill next time
|
| 67 | + mov wrnk,#5
|
| 68 | + lsl wrnk,#8 @ 0x500 @ nrv2e M2_MAX_OFFSET
|
| 69 | + b top_n2e
|
| 70 | +
|
| 71 | +eof_n2e:
|
| 72 | + pop {r3,r4} @ r3= orig_dst; r4= plen_dst
|
| 73 | + sub src,srclim @ 0 if actual src length equals expected length
|
| 74 | + sub dst,r3 @ actual dst length
|
| 75 | + str dst,[r4]
|
| 76 | + pop {r4,r5,r6,r7}
|
| 77 | + pop {r1}
|
| 78 | + bx r1
|
| 79 | +
|
| 80 | +get1_n2e: @ In: Carry set [from adding 0x80000000 (1<<31) to itself]
|
| 81 | + ldrb bits,[src] @ zero-extend next byte
|
| 82 | + adc bits,bits @ double and insert CarryIn as low bit
|
| 83 | + add src,#1
|
| 84 | + lsl bits,#24 @ move to top byte, and set CarryOut from old bit 8
|
| 85 | + mov pc,lr @ return, stay in current (THUMB) mode
|
| 86 | +
|
| 87 | +lit_n2e:
|
| 88 | + ldrb tmp,[src]; add src,#1
|
| 89 | + strb tmp,[dst]; add dst,#1
|
| 90 | +top_n2e:
|
| 91 | + jnextb1 lit_n2e
|
| 92 | + mov cnt,#1; b getoff_n2e
|
| 93 | +
|
| 94 | +off_n2e:
|
| 95 | + sub cnt,#1
|
| 96 | + getnextb(cnt)
|
| 97 | +getoff_n2e:
|
| 98 | + getnextb(cnt)
|
| 99 | + jnextb0 off_n2e
|
| 100 | +
|
| 101 | + sub tmp,cnt,#3 @ set Carry
|
| 102 | + mov len,#0 @ Carry unaffected
|
| 103 | + blo offprev_n2e @ cnt was 2; tests Carry only
|
| 104 | + lsl tmp,#8
|
| 105 | + ldrb off,[src]; add src,#1 @ low 7+1 bits
|
| 106 | + orr off,tmp
|
| 107 | + mvn off,off; beq eof_n2e @ off= ~off
|
| 108 | + asr off,#1; bcs lenlast_n2e
|
| 109 | + b lenmore_n2e
|
| 110 | +
|
| 111 | +offprev_n2e:
|
| 112 | + jnextb1 lenlast_n2e
|
| 113 | +lenmore_n2e:
|
| 114 | + mov len,#1
|
| 115 | + jnextb1 lenlast_n2e
|
| 116 | +len_n2e:
|
| 117 | + getnextb(len)
|
| 118 | + jnextb0 len_n2e
|
| 119 | + add len,#6-2
|
| 120 | + b gotlen_n2e
|
| 121 | +
|
| 122 | +lenlast_n2e:
|
| 123 | + getnextb(len) @ 0,1,2,3
|
| 124 | + add len,#2
|
| 125 | +gotlen_n2e: @ 'cmn': add the inputs, set condition codes, discard the sum
|
| 126 | + cmn wrnk,off; bcs near_n2e @ within M2_MAX_OFFSET
|
| 127 | + add len,#1 @ too far away, so minimum match length is 3
|
| 128 | +near_n2e:
|
| 129 | + ldrb tmp,[dst] @ force cacheline allocate
|
| 130 | +copy_n2e:
|
| 131 | + ldrb tmp,[dst,off]
|
| 132 | + strb tmp,[dst]; add dst,#1
|
| 133 | + sub len,#1; bne copy_n2e
|
| 134 | + b top_n2e
|
| 135 | +
|
| 136 | + .size ucl_decompress, .-ucl_decompress
|
Index: embios/branches/4g_compat/snprintf.c |
— | — | @@ -0,0 +1,91 @@ |
| 2 | +/***************************************************************************
|
| 3 | + * __________ __ ___.
|
| 4 | + * Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
| 5 | + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
| 6 | + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
| 7 | + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
| 8 | + * \/ \/ \/ \/ \/
|
| 9 | + * $Id$
|
| 10 | + *
|
| 11 | + * Copyright (C) 2002 by Gary Czvitkovicz
|
| 12 | + *
|
| 13 | + * This program is free software; you can redistribute it and/or
|
| 14 | + * modify it under the terms of the GNU General Public License
|
| 15 | + * as published by the Free Software Foundation; either version 2
|
| 16 | + * of the License, or (at your option) any later version.
|
| 17 | + *
|
| 18 | + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
| 19 | + * KIND, either express or implied.
|
| 20 | + *
|
| 21 | + ****************************************************************************/
|
| 22 | +
|
| 23 | +/*
|
| 24 | + * Minimal printf and snprintf formatting functions
|
| 25 | + *
|
| 26 | + * These support %c %s %d and %x
|
| 27 | + * Field width and zero-padding flag only
|
| 28 | + */
|
| 29 | +
|
| 30 | +#include "global.h"
|
| 31 | +#include <stdio.h>
|
| 32 | +#include <stdarg.h>
|
| 33 | +#include <stdbool.h>
|
| 34 | +#include <limits.h>
|
| 35 | +#include "format.h"
|
| 36 | +
|
| 37 | +
|
| 38 | +struct for_snprintf {
|
| 39 | + unsigned char *ptr; /* where to store it */
|
| 40 | + size_t bytes; /* amount already stored */
|
| 41 | + size_t max; /* max amount to store */
|
| 42 | +};
|
| 43 | +
|
| 44 | +static int sprfunc(void *ptr, unsigned char letter)
|
| 45 | +{
|
| 46 | + struct for_snprintf *pr = (struct for_snprintf *)ptr;
|
| 47 | + if(pr->bytes < pr->max) {
|
| 48 | + *pr->ptr = letter;
|
| 49 | + pr->ptr++;
|
| 50 | + pr->bytes++;
|
| 51 | + return true;
|
| 52 | + }
|
| 53 | + return false; /* filled buffer */
|
| 54 | +}
|
| 55 | +
|
| 56 | +
|
| 57 | +int snprintf(char *buf, size_t size, const char *fmt, ...)
|
| 58 | +{
|
| 59 | + bool ok;
|
| 60 | + va_list ap;
|
| 61 | + struct for_snprintf pr;
|
| 62 | +
|
| 63 | + pr.ptr = (unsigned char *)buf;
|
| 64 | + pr.bytes = 0;
|
| 65 | + pr.max = size;
|
| 66 | +
|
| 67 | + va_start(ap, fmt);
|
| 68 | + ok = format(sprfunc, &pr, fmt, ap);
|
| 69 | + va_end(ap);
|
| 70 | +
|
| 71 | + /* make sure it ends with a trailing zero */
|
| 72 | + pr.ptr[(pr.bytes < pr.max) ? 0 : -1] = '\0';
|
| 73 | +
|
| 74 | + return pr.bytes;
|
| 75 | +}
|
| 76 | +
|
| 77 | +int vsnprintf(char *buf, size_t size, const char *fmt, va_list ap)
|
| 78 | +{
|
| 79 | + bool ok;
|
| 80 | + struct for_snprintf pr;
|
| 81 | +
|
| 82 | + pr.ptr = (unsigned char *)buf;
|
| 83 | + pr.bytes = 0;
|
| 84 | + pr.max = size;
|
| 85 | +
|
| 86 | + ok = format(sprfunc, &pr, fmt, ap);
|
| 87 | +
|
| 88 | + /* make sure it ends with a trailing zero */
|
| 89 | + pr.ptr[(pr.bytes < pr.max) ? 0 : -1] = '\0';
|
| 90 | +
|
| 91 | + return pr.bytes;
|
| 92 | +}
|
Index: embios/branches/4g_compat/init.c |
— | — | @@ -0,0 +1,36 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#include "global.h"
|
| 26 | +#include "lcdconsole.h"
|
| 27 | +
|
| 28 | +void init() INITCODE_ATTR;
|
| 29 | +void init()
|
| 30 | +{
|
| 31 | + lcdconsole_init();
|
| 32 | + lcdconsole_puts("emBIOS v" VERSION "\n\nStorage init...", 0, -1);
|
| 33 | + lcdconsole_update();
|
| 34 | + if (fat32_init()) lcdconsole_puts(" failed!\n", 0, -1);
|
| 35 | + else lcdconsole_puts(" done\n", 0, -1);
|
| 36 | + lcdconsole_update();
|
| 37 | +} |
\ No newline at end of file |
Index: embios/branches/4g_compat/global.h |
— | — | @@ -0,0 +1,45 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __GLOBAL_H__
|
| 26 | +#define __GLOBAL_H__
|
| 27 | +
|
| 28 | +#ifndef ASM_FILE
|
| 29 | +#include <stdint.h>
|
| 30 | +#include <stddef.h>
|
| 31 | +#endif
|
| 32 | +
|
| 33 | +#define VERSION "0.0.1pre"
|
| 34 | +
|
| 35 | +#define ICODE_ATTR __attribute__ ((section(".icode")))
|
| 36 | +#define ICONST_ATTR __attribute__ ((section(".irodata")))
|
| 37 | +#define IDATA_ATTR __attribute__ ((section(".idata")))
|
| 38 | +#define IBSS_ATTR __attribute__ ((section(".ibss")))
|
| 39 | +#define INITCODE_ATTR __attribute__ ((section(".initcode")))
|
| 40 | +#define INITCONST_ATTR __attribute__ ((section(".initrodata")))
|
| 41 | +#define INITDATA_ATTR __attribute__ ((section(".initdata")))
|
| 42 | +#define INITBSS_ATTR __attribute__ ((section(".initbss")))
|
| 43 | +
|
| 44 | +#include "target.h"
|
| 45 | +
|
| 46 | +#endif
|
Index: embios/branches/4g_compat/strlen.c |
— | — | @@ -0,0 +1,36 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#include "global.h"
|
| 26 | +#include <string.h>
|
| 27 | +#include <limits.h>
|
| 28 | +
|
| 29 | +size_t strlen(_CONST char *str)
|
| 30 | +{
|
| 31 | + _CONST char *start = str;
|
| 32 | +
|
| 33 | + while (*str)
|
| 34 | + str++;
|
| 35 | +
|
| 36 | + return str - start;
|
| 37 | +}
|
Index: embios/branches/4g_compat/console.h |
— | — | @@ -0,0 +1,39 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __CONSOLE_H__
|
| 26 | +#define __CONSOLE_H__
|
| 27 | +
|
| 28 | +
|
| 29 | +#include "global.h"
|
| 30 | +#include <stdarg.h>
|
| 31 | +
|
| 32 | +
|
| 33 | +void cputc(unsigned int consoles, char string) ICODE_ATTR;
|
| 34 | +void cputs(unsigned int consoles, const char* string) ICODE_ATTR;
|
| 35 | +int cprintf(unsigned int consoles, const char* fmt, ...) ICODE_ATTR;
|
| 36 | +int cvprintf(unsigned int consoles, const char* fmt, va_list ap) ICODE_ATTR;
|
| 37 | +void cflush(unsigned int consoles) ICODE_ATTR;
|
| 38 | +
|
| 39 | +
|
| 40 | +#endif
|
Index: embios/branches/4g_compat/snprintf.h |
— | — | @@ -0,0 +1,39 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __PANIC_H__
|
| 26 | +#define __PANIC_H__
|
| 27 | +
|
| 28 | +
|
| 29 | +#define __need___va_list
|
| 30 | +#include <stdarg.h>
|
| 31 | +#include "global.h"
|
| 32 | +
|
| 33 | +
|
| 34 | +int vsnprintf (char *buf, size_t size, const char *fmt, __VALIST ap);
|
| 35 | +
|
| 36 | +int snprintf (char *buf, size_t size, const char *fmt, ...)
|
| 37 | + ATTRIBUTE_PRINTF(3, 4);
|
| 38 | +
|
| 39 | +
|
| 40 | +#endif
|
Index: embios/branches/4g_compat/util.c |
— | — | @@ -0,0 +1,52 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#include "global.h"
|
| 26 | +#include "util.h"
|
| 27 | +
|
| 28 | +
|
| 29 | +void* memcpy(void* destination, const void* source, size_t num)
|
| 30 | +{
|
| 31 | + unsigned char* dest = (unsigned char*)destination;
|
| 32 | + unsigned char* src = (unsigned char*)source;
|
| 33 | + while (num--) *dest++ = *src++;
|
| 34 | + return destination;
|
| 35 | +}
|
| 36 | +
|
| 37 | +void* memset(void* ptr, int value, size_t num)
|
| 38 | +{
|
| 39 | + unsigned char* dest = (unsigned char*)ptr;
|
| 40 | + while (num--) *dest++ = (unsigned char)value;
|
| 41 | + return ptr;
|
| 42 | +}
|
| 43 | +
|
| 44 | +int memcmp(const void* ptr1, const void* ptr2, size_t num)
|
| 45 | +{
|
| 46 | + unsigned char* src1 = (unsigned char*)ptr1;
|
| 47 | + unsigned char* src2 = (unsigned char*)ptr2;
|
| 48 | + int diff;
|
| 49 | + while (num--)
|
| 50 | + if (diff = *src1++ - *src2++)
|
| 51 | + return diff;
|
| 52 | + return 0;
|
| 53 | +}
|
Index: embios/branches/4g_compat/fat32.c |
— | — | @@ -0,0 +1,349 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#include "global.h"
|
| 26 | +#include "storage.h"
|
| 27 | +#include "fat32.h"
|
| 28 | +#include "util.h"
|
| 29 | +
|
| 30 | +
|
| 31 | +uint32_t fat32_ok;
|
| 32 | +uint32_t fat32_startsector;
|
| 33 | +uint32_t fat32_secperclus;
|
| 34 | +uint32_t fat32_database;
|
| 35 | +uint32_t fat32_fatbase;
|
| 36 | +uint32_t fat32_fatsize;
|
| 37 | +uint32_t fat32_fatcount;
|
| 38 | +uint32_t fat32_sectorcount;
|
| 39 | +uint32_t fat32_clustercount;
|
| 40 | +uint32_t fat32_rootdirclus;
|
| 41 | +uint32_t fat32_buf1[0x200] __attribute__((aligned(16)));
|
| 42 | +uint32_t fat32_buf2[0x200] __attribute__((aligned(16)));
|
| 43 | +
|
| 44 | +
|
| 45 | +uint32_t fat32_get_root()
|
| 46 | +{
|
| 47 | + return fat32_rootdirclus;
|
| 48 | +}
|
| 49 | +
|
| 50 | +uint32_t fat32_get_clusterchain(uint32_t clusterchain, uint32_t maxsize, void* buffer)
|
| 51 | +{
|
| 52 | + uint32_t i;
|
| 53 | + for (i = 0; i < (maxsize >> 11); )
|
| 54 | + {
|
| 55 | + uint32_t sector = (clusterchain - 2) * fat32_secperclus + fat32_database;
|
| 56 | + uint32_t count = fat32_secperclus;
|
| 57 | + if (count + i > (maxsize >> 11)) count = (maxsize >> 11) - i;
|
| 58 | + uint32_t fatsector = fat32_fatbase + (clusterchain >> 9);
|
| 59 | + if (storage_read(fatsector, 1, &((uint32_t*)buffer)[i << 9])) return 1;
|
| 60 | + clusterchain = ((uint32_t*)buffer)[(i << 9) + (clusterchain & 0x1FF)];
|
| 61 | + if (storage_read(sector, count, &((uint32_t*)buffer)[i << 9])) return 1;
|
| 62 | + i += count;
|
| 63 | + if (clusterchain >= 0x0ffffff0) return 0;
|
| 64 | + }
|
| 65 | + return clusterchain;
|
| 66 | +}
|
| 67 | +
|
| 68 | +uint32_t fat32_get_direntry(uint32_t clusterchain, const char* filename, uint32_t* filesize)
|
| 69 | +{
|
| 70 | + uint32_t i, j;
|
| 71 | + while (clusterchain > 1 && clusterchain < 0x0ffffff0)
|
| 72 | + {
|
| 73 | + uint32_t sector = (clusterchain - 2) * fat32_secperclus + fat32_database;
|
| 74 | + for (j = 0; j < fat32_secperclus; j++)
|
| 75 | + {
|
| 76 | + if (storage_read(sector + j, 1, fat32_buf1)) return 1;
|
| 77 | + for (i = 0; i < 0x200; i += 8)
|
| 78 | + if (((uint8_t*)fat32_buf1)[i << 2] == 0) return 0;
|
| 79 | + else if (((uint8_t*)fat32_buf1)[i << 2] == 0xe5) continue;
|
| 80 | + else if (memcmp(&fat32_buf1[i], filename, 11) == 0)
|
| 81 | + {
|
| 82 | + *filesize = fat32_buf1[i + 7];
|
| 83 | + return (((uint16_t*)fat32_buf1)[(i << 1) + 0xA] << 16)
|
| 84 | + | ((uint16_t*)fat32_buf1)[(i << 1) + 0xD];
|
| 85 | + }
|
| 86 | + }
|
| 87 | + uint32_t fatsector = fat32_fatbase + (clusterchain >> 9);
|
| 88 | + if (storage_read(fatsector, 1, fat32_buf1)) return 1;
|
| 89 | + clusterchain = fat32_buf1[(i << 9) + (clusterchain & 0x1FF)];
|
| 90 | + }
|
| 91 | + return 0;
|
| 92 | +}
|
| 93 | +
|
| 94 | +uint32_t fat32_delete_clusterchain(uint32_t clusterchain)
|
| 95 | +{
|
| 96 | + while (1)
|
| 97 | + {
|
| 98 | + uint32_t fatsector = fat32_fatbase + (clusterchain >> 9);
|
| 99 | + if (storage_read(fatsector, 1, fat32_buf1)) return 1;
|
| 100 | + clusterchain = fat32_buf1[clusterchain & 0x1FF];
|
| 101 | + fat32_buf1[(clusterchain & 0x1FF)] = 0;
|
| 102 | + if (storage_write(fatsector, 1, fat32_buf1)) return 1;
|
| 103 | + if (clusterchain >= 0x0ffffff0) return 0;
|
| 104 | + }
|
| 105 | +}
|
| 106 | +
|
| 107 | +uint32_t fat32_delete_direntry(uint32_t clusterchain, const char* filename)
|
| 108 | +{
|
| 109 | + uint32_t i, j;
|
| 110 | + while (clusterchain > 1 && clusterchain < 0x0ffffff0)
|
| 111 | + {
|
| 112 | + uint32_t sector = (clusterchain - 2) * fat32_secperclus + fat32_database;
|
| 113 | + for (j = 0; j < fat32_secperclus; j++)
|
| 114 | + {
|
| 115 | + if (storage_read(sector + j, 1, fat32_buf1)) return 1;
|
| 116 | + for (i = 0; i < 0x200; i += 8)
|
| 117 | + if (((uint8_t*)fat32_buf1)[i << 2] == 0) return 0;
|
| 118 | + else if (((uint8_t*)fat32_buf1)[i << 2] == 0xe5) continue;
|
| 119 | + else if (memcmp(&fat32_buf1[i], filename, 11) == 0)
|
| 120 | + {
|
| 121 | + ((uint8_t*)fat32_buf1)[i << 2] = 0xe5;
|
| 122 | + if (storage_write(sector + j, 1, fat32_buf1)) return 1;
|
| 123 | + return 0;
|
| 124 | + }
|
| 125 | + }
|
| 126 | + uint32_t fatsector = fat32_fatbase + (clusterchain >> 9);
|
| 127 | + if (storage_read(fatsector, 1, fat32_buf1)) return 1;
|
| 128 | + clusterchain = fat32_buf1[(i << 9) + (clusterchain & 0x1FF)];
|
| 129 | + }
|
| 130 | + return 0;
|
| 131 | +}
|
| 132 | +
|
| 133 | +uint32_t fat32_store_stream(void* buffer, uint32_t size)
|
| 134 | +{
|
| 135 | + uint32_t i;
|
| 136 | + uint32_t clusterchain = 0;
|
| 137 | + uint32_t scanidx = 2;
|
| 138 | + uint32_t scansect = 0xffffffff;
|
| 139 | + uint32_t lastidx;
|
| 140 | + uint32_t lastsect = 0xffffffff;
|
| 141 | + uint32_t dirty = 0;
|
| 142 | + while (size)
|
| 143 | + {
|
| 144 | + while (scanidx < fat32_clustercount + 2)
|
| 145 | + {
|
| 146 | + if ((scanidx >> 9) != scansect)
|
| 147 | + {
|
| 148 | + scansect = scanidx >> 9;
|
| 149 | + if (storage_read(fat32_fatbase + scansect, 1, fat32_buf1)) return 0;
|
| 150 | + }
|
| 151 | + if (!fat32_buf1[scanidx & 0x1ff]) break;
|
| 152 | + scanidx++;
|
| 153 | + }
|
| 154 | + if (scanidx >= fat32_clustercount + 2) return 0;
|
| 155 | + if (!clusterchain) clusterchain = scanidx;
|
| 156 | + else
|
| 157 | + {
|
| 158 | + fat32_buf2[lastidx & 0x1ff] = scanidx;
|
| 159 | + dirty = 1;
|
| 160 | + }
|
| 161 | + lastidx = scanidx;
|
| 162 | + if ((lastidx >> 9) != lastsect)
|
| 163 | + {
|
| 164 | + if (dirty)
|
| 165 | + if (storage_write(fat32_fatbase + lastsect, 1, fat32_buf2)) return 0;
|
| 166 | + dirty = 0;
|
| 167 | + lastsect = lastidx >> 9;
|
| 168 | + memcpy(fat32_buf2, fat32_buf1, 0x800);
|
| 169 | + }
|
| 170 | + uint32_t sector = (scanidx - 2) * fat32_secperclus + fat32_database;
|
| 171 | + uint32_t count = (size + 0x7ff) >> 11;
|
| 172 | + if (count > fat32_secperclus) count = fat32_secperclus;
|
| 173 | + if (storage_write(sector, count, &((uint32_t*)buffer)[i << 9])) return 0;
|
| 174 | + if ((count << 11) >= size)
|
| 175 | + {
|
| 176 | + fat32_buf2[lastidx & 0x1ff] = 0x0fffffff;
|
| 177 | + if (storage_write(fat32_fatbase + lastsect, 1, fat32_buf2)) return 0;
|
| 178 | + break;
|
| 179 | + }
|
| 180 | + size -= count << 11;
|
| 181 | + buffer = (void*)((uint32_t)buffer + (count << 11));
|
| 182 | + scanidx++;
|
| 183 | + }
|
| 184 | + return clusterchain;
|
| 185 | +}
|
| 186 | +
|
| 187 | +void fat32_set_direntry(uint32_t* ptr, const char* filename, uint32_t filechain,
|
| 188 | + uint32_t filesize, uint32_t flags)
|
| 189 | +{
|
| 190 | + memcpy(ptr, filename, 11);
|
| 191 | + ((uint16_t*)ptr)[0xa] = filechain >> 16;
|
| 192 | + ((uint8_t*)ptr)[0xb] = flags;
|
| 193 | + ((uint16_t*)ptr)[0xa] = filechain >> 16;
|
| 194 | + ((uint16_t*)ptr)[0xd] = filechain & 0xffff;
|
| 195 | + ptr[7] = filesize;
|
| 196 | +}
|
| 197 | +
|
| 198 | +uint32_t fat32_store_direntry(uint32_t dirchain, const char* filename,
|
| 199 | + uint32_t filechain, uint32_t filesize, uint32_t flags)
|
| 200 | +{
|
| 201 | + uint32_t i, j;
|
| 202 | + uint32_t lastidx;
|
| 203 | + while (dirchain > 1 && dirchain < 0x0ffffff0)
|
| 204 | + {
|
| 205 | + uint32_t sector = (dirchain - 2) * fat32_secperclus + fat32_database;
|
| 206 | + for (j = 0; j < fat32_secperclus; j++)
|
| 207 | + {
|
| 208 | + if (storage_read(sector + j, 1, fat32_buf1)) return 1;
|
| 209 | + for (i = 0; i < 0x200; i += 8)
|
| 210 | + if (((uint8_t*)fat32_buf1)[i << 2] == 0
|
| 211 | + || ((uint8_t*)fat32_buf1)[i << 2] == 0xe5)
|
| 212 | + {
|
| 213 | + fat32_set_direntry(&fat32_buf1[i], filename, filechain, filesize, flags);
|
| 214 | + if (storage_write(sector + j, 1, fat32_buf1)) return 1;
|
| 215 | + return 0;
|
| 216 | + }
|
| 217 | + }
|
| 218 | + uint32_t fatsector = fat32_fatbase + (dirchain >> 9);
|
| 219 | + if (storage_read(fatsector, 1, fat32_buf1)) return 1;
|
| 220 | + lastidx = dirchain;
|
| 221 | + dirchain = fat32_buf1[(i << 9) + (dirchain & 0x1FF)];
|
| 222 | + }
|
| 223 | + uint32_t scanidx = 2;
|
| 224 | + uint32_t scansect = 0xffffffff;
|
| 225 | + while (scanidx < fat32_clustercount + 2)
|
| 226 | + {
|
| 227 | + if ((scanidx >> 9) != scansect)
|
| 228 | + {
|
| 229 | + scansect = scanidx >> 9;
|
| 230 | + if (storage_read(fat32_fatbase + scansect, 1, fat32_buf1)) return 1;
|
| 231 | + }
|
| 232 | + if (!fat32_buf1[scanidx & 0x1ff]) break;
|
| 233 | + scanidx++;
|
| 234 | + }
|
| 235 | + if (scanidx >= fat32_clustercount + 2) return 1;
|
| 236 | + fat32_buf1[scanidx & 0x1ff] = 0x0fffffff;
|
| 237 | + if (storage_write(fat32_fatbase + scansect, 1, fat32_buf1)) return 1;
|
| 238 | + if (storage_read(fat32_fatbase + (lastidx >> 9), 1, fat32_buf1)) return 1;
|
| 239 | + fat32_buf1[lastidx & 0x1ff] = scanidx;
|
| 240 | + if (storage_write(fat32_fatbase + scansect, 1, fat32_buf1)) return 1;
|
| 241 | + uint32_t sector = (scanidx - 2) * fat32_secperclus + fat32_database;
|
| 242 | + for (i = 0; i < fat32_secperclus; i++)
|
| 243 | + {
|
| 244 | + memset(fat32_buf1, 0, 0x800);
|
| 245 | + if (!i) fat32_set_direntry(fat32_buf1, filename, filechain, filesize, flags);
|
| 246 | + if (storage_write(sector + i, 1, fat32_buf1)) return 1;
|
| 247 | + }
|
| 248 | + return 0;
|
| 249 | +}
|
| 250 | +
|
| 251 | +uint32_t fat32_create_dir(uint32_t parent, const char* dirname)
|
| 252 | +{
|
| 253 | + uint32_t i;
|
| 254 | + uint32_t scanidx = 2;
|
| 255 | + uint32_t scansect = 0xffffffff;
|
| 256 | + while (scanidx < fat32_clustercount + 2)
|
| 257 | + {
|
| 258 | + if ((scanidx >> 9) != scansect)
|
| 259 | + {
|
| 260 | + scansect = scanidx >> 9;
|
| 261 | + if (storage_read(fat32_fatbase + scansect, 1, fat32_buf1)) return 0;
|
| 262 | + }
|
| 263 | + if (!fat32_buf1[scanidx & 0x1ff]) break;
|
| 264 | + scanidx++;
|
| 265 | + }
|
| 266 | + if (scanidx >= fat32_clustercount + 2) return 0;
|
| 267 | + fat32_buf1[scanidx & 0x1ff] = 0x0fffffff;
|
| 268 | + if (storage_write(fat32_fatbase + scansect, 1, fat32_buf1)) return 0;
|
| 269 | + fat32_store_direntry(parent, dirname, scanidx, 0, 0x10);
|
| 270 | + uint32_t sector = (scanidx - 2) * fat32_secperclus + fat32_database;
|
| 271 | + for (i = 0; i < fat32_secperclus; i++)
|
| 272 | + {
|
| 273 | + memset(fat32_buf1, 0, 0x800);
|
| 274 | + if (!i)
|
| 275 | + {
|
| 276 | + fat32_set_direntry(fat32_buf1, ". ", scanidx, 0, 0x10);
|
| 277 | + if (parent == fat32_rootdirclus) parent = 0;
|
| 278 | + fat32_set_direntry(&fat32_buf1[8], ".. ", parent, 0, 0x10);
|
| 279 | + }
|
| 280 | + if (storage_write(sector + i, 1, fat32_buf1)) return 0;
|
| 281 | + }
|
| 282 | + return scanidx;
|
| 283 | +}
|
| 284 | +
|
| 285 | +uint32_t fat32_read_file(const char* filename, uint32_t maxsize, void* buffer, uint32_t* filesize)
|
| 286 | +{
|
| 287 | +}
|
| 288 | +
|
| 289 | +uint32_t fat32_get_partition_start()
|
| 290 | +{
|
| 291 | + return fat32_startsector;
|
| 292 | +}
|
| 293 | +
|
| 294 | +uint32_t fat32_init()
|
| 295 | +{
|
| 296 | + uint32_t i;
|
| 297 | + fat32_ok = 0;
|
| 298 | + fat32_startsector = 0xFFFFFFFF;
|
| 299 | + if (storage_init()) return 1;
|
| 300 | +
|
| 301 | + if (storage_read(0, 1, fat32_buf1)) return 1;
|
| 302 | +
|
| 303 | + if (*((uint16_t*)((uint32_t)fat32_buf1 + 0x1FE)) != 0xAA55)
|
| 304 | + {
|
| 305 | + return 1;
|
| 306 | + }
|
| 307 | +
|
| 308 | + for (i = 0x1C2; i < 0x200; i += 0x10)
|
| 309 | + if (((uint8_t*)fat32_buf1)[i] == 0xB)
|
| 310 | + {
|
| 311 | + fat32_startsector = *((uint16_t*)((uint32_t)fat32_buf1 + i + 4))
|
| 312 | + | (*((uint16_t*)((uint32_t)fat32_buf1 + i + 6)) << 16);
|
| 313 | + break;
|
| 314 | + }
|
| 315 | +
|
| 316 | + if (fat32_startsector == 0xFFFFFFFF
|
| 317 | + && *((uint16_t*)((uint32_t)fat32_buf1 + 0x52)) == 0x4146
|
| 318 | + && *((uint8_t*)((uint32_t)fat32_buf1 + 0x54)) == 0x54)
|
| 319 | + fat32_startsector = 0;
|
| 320 | +
|
| 321 | + if (fat32_startsector == 0xFFFFFFFF) return 1;
|
| 322 | +
|
| 323 | + if (storage_read(fat32_startsector, 1, fat32_buf1)) return 1;
|
| 324 | +
|
| 325 | + if (*((uint16_t*)((uint32_t)fat32_buf1 + 0x1FE)) != 0xAA55) return 1;
|
| 326 | +
|
| 327 | + if (((uint8_t*)fat32_buf1)[0xB] != 0 || ((uint8_t*)fat32_buf1)[0xC] != 8) return 1;
|
| 328 | +
|
| 329 | + fat32_secperclus = ((uint8_t*)fat32_buf1)[0xD];
|
| 330 | + uint32_t reserved = ((uint16_t*)fat32_buf1)[0x7];
|
| 331 | + fat32_fatcount = ((uint8_t*)fat32_buf1)[0x10];
|
| 332 | +
|
| 333 | + if (((uint8_t*)fat32_buf1)[0x11] != 0) return 1;
|
| 334 | +
|
| 335 | + fat32_sectorcount = fat32_buf1[8];
|
| 336 | + fat32_fatsize = fat32_buf1[9];
|
| 337 | +
|
| 338 | + if (((uint16_t*)fat32_buf1)[0x15] != 0) return 1;
|
| 339 | +
|
| 340 | + fat32_rootdirclus = fat32_buf1[0xB];
|
| 341 | +
|
| 342 | + fat32_clustercount = (fat32_sectorcount - reserved
|
| 343 | + - fat32_fatcount * fat32_fatsize) / fat32_secperclus;
|
| 344 | +
|
| 345 | + fat32_fatbase = fat32_startsector + reserved;
|
| 346 | + fat32_database = fat32_fatbase + fat32_fatcount * fat32_fatsize;
|
| 347 | +
|
| 348 | + fat32_ok = 1;
|
| 349 | + return 0;
|
| 350 | +}
|
Index: embios/branches/4g_compat/util.h |
— | — | @@ -0,0 +1,36 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __UTIL_H__
|
| 26 | +#define __UTIL_H__
|
| 27 | +
|
| 28 | +
|
| 29 | +#include "global.h"
|
| 30 | +
|
| 31 | +
|
| 32 | +void* memcpy(void* destination, const void* source, size_t num) ICODE_ATTR;
|
| 33 | +void* memset(void* ptr, int value, size_t num) ICODE_ATTR;
|
| 34 | +int memcmp(const void* ptr1, const void* ptr2, size_t num) ICODE_ATTR;
|
| 35 | +
|
| 36 | +
|
| 37 | +#endif
|
Index: embios/branches/4g_compat/main.c |
— | — | @@ -0,0 +1,29 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#include "global.h"
|
| 26 | +
|
| 27 | +void main()
|
| 28 | +{
|
| 29 | + panic("main() doesn't know what to do!");
|
| 30 | +} |
\ No newline at end of file |
Index: embios/branches/4g_compat/fat32.h |
— | — | @@ -0,0 +1,44 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __FAT32_H__
|
| 26 | +#define __FAT32_H__
|
| 27 | +
|
| 28 | +#include "global.h"
|
| 29 | +
|
| 30 | +uint32_t fat32_get_root();
|
| 31 | +uint32_t fat32_get_clusterchain(uint32_t clusterchain, uint32_t maxsize, void* buffer);
|
| 32 | +uint32_t fat32_get_direntry(uint32_t clusterchain, const char* filename, uint32_t* filesize);
|
| 33 | +uint32_t fat32_delete_clusterchain(uint32_t clusterchain);
|
| 34 | +uint32_t fat32_delete_direntry(uint32_t clusterchain, const char* filename);
|
| 35 | +uint32_t fat32_store_stream(void* buffer, uint32_t size);
|
| 36 | +uint32_t fat32_store_direntry(uint32_t dirchain, const char* filename,
|
| 37 | + uint32_t filechain, uint32_t filesize, uint32_t flags);
|
| 38 | +uint32_t fat32_create_dir(uint32_t parent, const char* dirname);
|
| 39 | +uint32_t fat32_read_file(const char* filename, uint32_t maxsize, void* buffer, uint32_t* filesize);
|
| 40 | +uint32_t fat32_resize_patchdirs(uint32_t clusterchain, uint32_t clustoffset);
|
| 41 | +uint32_t fat32_resize_fulldisk();
|
| 42 | +uint32_t fat32_get_partition_start();
|
| 43 | +uint32_t fat32_init();
|
| 44 | +
|
| 45 | +#endif
|
Index: embios/branches/4g_compat/format.c |
— | — | @@ -0,0 +1,192 @@ |
| 2 | +/***************************************************************************
|
| 3 | + * __________ __ ___.
|
| 4 | + * Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
| 5 | + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
| 6 | + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
| 7 | + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
| 8 | + * \/ \/ \/ \/ \/
|
| 9 | + * $Id$
|
| 10 | + *
|
| 11 | + * Copyright (C) 2002 by Gary Czvitkovicz
|
| 12 | + *
|
| 13 | + * This program is free software; you can redistribute it and/or
|
| 14 | + * modify it under the terms of the GNU General Public License
|
| 15 | + * as published by the Free Software Foundation; either version 2
|
| 16 | + * of the License, or (at your option) any later version.
|
| 17 | + *
|
| 18 | + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
| 19 | + * KIND, either express or implied.
|
| 20 | + *
|
| 21 | + ****************************************************************************/
|
| 22 | +
|
| 23 | +
|
| 24 | +#include <stdarg.h>
|
| 25 | +#include <stdbool.h>
|
| 26 | +#include <limits.h>
|
| 27 | +#include <string.h>
|
| 28 | +
|
| 29 | +static const char hexdigit[] = "0123456789ABCDEF";
|
| 30 | +
|
| 31 | +int format(
|
| 32 | + /* call 'push()' for each output letter */
|
| 33 | + int (*push)(void *userp, unsigned char data),
|
| 34 | + void *userp,
|
| 35 | + const char *fmt,
|
| 36 | + va_list ap)
|
| 37 | +{
|
| 38 | + char *str;
|
| 39 | + char tmpbuf[12], pad;
|
| 40 | + int ch, width, val, sign, precision;
|
| 41 | + long lval, lsign;
|
| 42 | + unsigned int uval;
|
| 43 | + unsigned long ulval;
|
| 44 | + bool ok = true;
|
| 45 | +
|
| 46 | + tmpbuf[sizeof tmpbuf - 1] = '\0';
|
| 47 | +
|
| 48 | + while ((ch = *fmt++) != '\0' && ok)
|
| 49 | + {
|
| 50 | + if (ch == '%')
|
| 51 | + {
|
| 52 | + ch = *fmt++;
|
| 53 | + pad = ' ';
|
| 54 | + if (ch == '0')
|
| 55 | + pad = '0';
|
| 56 | +
|
| 57 | + width = 0;
|
| 58 | + while (ch >= '0' && ch <= '9')
|
| 59 | + {
|
| 60 | + width = 10*width + ch - '0';
|
| 61 | + ch = *fmt++;
|
| 62 | + }
|
| 63 | +
|
| 64 | + precision = 0;
|
| 65 | + if(ch == '.')
|
| 66 | + {
|
| 67 | + ch = *fmt++;
|
| 68 | + while (ch >= '0' && ch <= '9')
|
| 69 | + {
|
| 70 | + precision = 10*precision + ch - '0';
|
| 71 | + ch = *fmt++;
|
| 72 | + }
|
| 73 | + } else {
|
| 74 | + precision = INT_MAX;
|
| 75 | + }
|
| 76 | +
|
| 77 | + str = tmpbuf + sizeof tmpbuf - 1;
|
| 78 | + switch (ch)
|
| 79 | + {
|
| 80 | + case 'c':
|
| 81 | + *--str = va_arg (ap, int);
|
| 82 | + break;
|
| 83 | +
|
| 84 | + case 's':
|
| 85 | + str = va_arg (ap, char*);
|
| 86 | + break;
|
| 87 | +
|
| 88 | + case 'd':
|
| 89 | + val = sign = va_arg (ap, int);
|
| 90 | + if (val < 0)
|
| 91 | + val = -val;
|
| 92 | + do
|
| 93 | + {
|
| 94 | + *--str = (val % 10) + '0';
|
| 95 | + val /= 10;
|
| 96 | + }
|
| 97 | + while (val > 0);
|
| 98 | + if (sign < 0)
|
| 99 | + *--str = '-';
|
| 100 | + break;
|
| 101 | +
|
| 102 | + case 'u':
|
| 103 | + uval = va_arg(ap, unsigned int);
|
| 104 | + do
|
| 105 | + {
|
| 106 | + *--str = (uval % 10) + '0';
|
| 107 | + uval /= 10;
|
| 108 | + }
|
| 109 | + while (uval > 0);
|
| 110 | + break;
|
| 111 | +
|
| 112 | + case 'x':
|
| 113 | + case 'X':
|
| 114 | + pad='0';
|
| 115 | + uval = va_arg (ap, int);
|
| 116 | + do
|
| 117 | + {
|
| 118 | + *--str = hexdigit[uval & 0xf];
|
| 119 | + uval >>= 4;
|
| 120 | + }
|
| 121 | + while (uval);
|
| 122 | + break;
|
| 123 | +
|
| 124 | + case 'l':
|
| 125 | + case 'z': /* assume sizeof(size_t) == sizeof(long) */
|
| 126 | + ch = *fmt++;
|
| 127 | + switch(ch) {
|
| 128 | + case 'x':
|
| 129 | + case 'X':
|
| 130 | + pad='0';
|
| 131 | + ulval = va_arg (ap, long);
|
| 132 | + do
|
| 133 | + {
|
| 134 | + *--str = hexdigit[ulval & 0xf];
|
| 135 | + ulval >>= 4;
|
| 136 | + }
|
| 137 | + while (ulval);
|
| 138 | + break;
|
| 139 | + case 'd':
|
| 140 | + lval = lsign = va_arg (ap, long);
|
| 141 | + if (lval < 0)
|
| 142 | + lval = -lval;
|
| 143 | + do
|
| 144 | + {
|
| 145 | + *--str = (lval % 10) + '0';
|
| 146 | + lval /= 10;
|
| 147 | + }
|
| 148 | + while (lval > 0);
|
| 149 | + if (lsign < 0)
|
| 150 | + *--str = '-';
|
| 151 | + break;
|
| 152 | +
|
| 153 | + case 'u':
|
| 154 | + ulval = va_arg(ap, unsigned long);
|
| 155 | + do
|
| 156 | + {
|
| 157 | + *--str = (ulval % 10) + '0';
|
| 158 | + ulval /= 10;
|
| 159 | + }
|
| 160 | + while (ulval > 0);
|
| 161 | + break;
|
| 162 | +
|
| 163 | + default:
|
| 164 | + *--str = 'l';
|
| 165 | + *--str = ch;
|
| 166 | + }
|
| 167 | +
|
| 168 | + break;
|
| 169 | +
|
| 170 | + default:
|
| 171 | + *--str = ch;
|
| 172 | + break;
|
| 173 | + }
|
| 174 | +
|
| 175 | + if (width > 0)
|
| 176 | + {
|
| 177 | + width -= strlen (str);
|
| 178 | + while (width-- > 0 && ok)
|
| 179 | + ok=push(userp, pad);
|
| 180 | + }
|
| 181 | + while (*str != '\0' && ok && precision--)
|
| 182 | + ok=push(userp, *str++);
|
| 183 | + }
|
| 184 | + else
|
| 185 | + ok=push(userp, ch);
|
| 186 | + }
|
| 187 | + return ok; /* true means good */
|
| 188 | +}
|
| 189 | +
|
| 190 | +int vuprintf(int (*push)(void *userp, unsigned char data), void *userp, const char *fmt, va_list ap)
|
| 191 | +{
|
| 192 | + return format(push, userp, fmt, ap);
|
| 193 | +}
|
Index: embios/branches/4g_compat/ucl.h |
— | — | @@ -0,0 +1,34 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __UCL_H__
|
| 26 | +#define __UCL_H__
|
| 27 | +
|
| 28 | +
|
| 29 | +#include "global.h"
|
| 30 | +
|
| 31 | +
|
| 32 | +uint32_t ucl_decompress(const void* src, uint32_t len_src, void* dst, uint32_t* plen_dst);
|
| 33 | +
|
| 34 | +
|
| 35 | +#endif
|
Index: embios/branches/4g_compat/lcdconsole.h |
— | — | @@ -0,0 +1,45 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#ifndef __LCDCONSOLE_H__
|
| 26 | +#define __LCDCONSOLE_H__
|
| 27 | +
|
| 28 | +
|
| 29 | +#include "global.h"
|
| 30 | +#include "drawing.h"
|
| 31 | +#include "lcd.h"
|
| 32 | +
|
| 33 | +
|
| 34 | +#define LCDCONSOLE_COLS (LCD_WIDTH / FONT_WIDTH)
|
| 35 | +#define LCDCONSOLE_ROWS (LCD_HEIGHT / FONT_HEIGHT)
|
| 36 | +#define LCDCONSOLE_OFFSETX ((LCD_WIDTH - LCDCONSOLE_COLS * FONT_WIDTH) / 2)
|
| 37 | +#define LCDCONSOLE_OFFSETY ((LCD_HEIGHT - LCDCONSOLE_ROWS * FONT_HEIGHT) / 2)
|
| 38 | +
|
| 39 | +
|
| 40 | +void lcdconsole_init();
|
| 41 | +void lcdconsole_putc(char string, int fgcolor, int bgcolor) ICODE_ATTR;
|
| 42 | +void lcdconsole_puts(const char* string, int fgcolor, int bgcolor) ICODE_ATTR;
|
| 43 | +void lcdconsole_update() ICODE_ATTR;
|
| 44 | +
|
| 45 | +
|
| 46 | +#endif
|
Index: embios/branches/4g_compat/panic.c |
— | — | @@ -0,0 +1,55 @@ |
| 2 | +//
|
| 3 | +//
|
| 4 | +// Copyright 2010 TheSeven
|
| 5 | +//
|
| 6 | +//
|
| 7 | +// This file is part of emBIOS.
|
| 8 | +//
|
| 9 | +// emBIOS is free software: you can redistribute it and/or
|
| 10 | +// modify it under the terms of the GNU General Public License as
|
| 11 | +// published by the Free Software Foundation, either version 2 of the
|
| 12 | +// License, or (at your option) any later version.
|
| 13 | +//
|
| 14 | +// emBIOS is distributed in the hope that it will be useful,
|
| 15 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 16 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
| 17 | +// See the GNU General Public License for more details.
|
| 18 | +//
|
| 19 | +// You should have received a copy of the GNU General Public License along
|
| 20 | +// with emBIOS. If not, see <http://www.gnu.org/licenses/>.
|
| 21 | +//
|
| 22 | +//
|
| 23 | +
|
| 24 | +
|
| 25 | +#include "global.h"
|
| 26 | +#include "console.h"
|
| 27 | +
|
| 28 | +
|
| 29 | +void handle_panic()
|
| 30 | +{
|
| 31 | + while(1);
|
| 32 | +}
|
| 33 | +
|
| 34 | +void panic(const char* string)
|
| 35 | +{
|
| 36 | + cputs(1, "\n*PANIC*\n");
|
| 37 | + cputs(1, string);
|
| 38 | + cputc(1, '\n');
|
| 39 | + handle_panic();
|
| 40 | +}
|
| 41 | +
|
| 42 | +void panicf(const char* string, ...)
|
| 43 | +{
|
| 44 | + va_list ap;
|
| 45 | + cputs(1, "\n*PANIC*\n");
|
| 46 | + va_start(ap, string);
|
| 47 | + cvprintf(1, string, ap);
|
| 48 | + va_end(ap);
|
| 49 | + cputc(1, '\n');
|
| 50 | + handle_panic();
|
| 51 | +}
|
| 52 | +
|
| 53 | +void __div0()
|
| 54 | +{
|
| 55 | + panic("Division by zero!");
|
| 56 | +}
|
Index: embios/branches/4g_compat/format.h |
— | — | @@ -0,0 +1,37 @@ |
| 2 | +/***************************************************************************
|
| 3 | + * __________ __ ___.
|
| 4 | + * Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
| 5 | + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
| 6 | + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
| 7 | + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
| 8 | + * \/ \/ \/ \/ \/
|
| 9 | + * $Id$
|
| 10 | + *
|
| 11 | + * Copyright (C) 2002 by Felix Arends
|
| 12 | + *
|
| 13 | + * This program is free software; you can redistribute it and/or
|
| 14 | + * modify it under the terms of the GNU General Public License
|
| 15 | + * as published by the Free Software Foundation; either version 2
|
| 16 | + * of the License, or (at your option) any later version.
|
| 17 | + *
|
| 18 | + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
| 19 | + * KIND, either express or implied.
|
| 20 | + *
|
| 21 | + ****************************************************************************/
|
| 22 | +
|
| 23 | +#ifndef __FORMAT_H__
|
| 24 | +#define __FORMAT_H__
|
| 25 | +
|
| 26 | +int format(
|
| 27 | + /* call 'push()' for each output letter */
|
| 28 | + int (*push)(void *userp, unsigned char data),
|
| 29 | + void *userp,
|
| 30 | + const char *fmt,
|
| 31 | + va_list ap);
|
| 32 | +
|
| 33 | +/* callback function is called for every output character (byte) with userp and
|
| 34 | + * should return 0 when ch is a char other than '\0' that should stop printing */
|
| 35 | +int vuprintf(int (*push)(void *userp, unsigned char data),
|
| 36 | + void *userp, const char *fmt, va_list ap);
|
| 37 | +
|
| 38 | +#endif /* __FORMAT_H__ */
|
Index: embios/branches/4g_compat |
Property changes on: embios/branches/4g_compat |
___________________________________________________________________ |
Added: svn:ignore |
## -0,0 +1 ## |
| 39 | +build |